1  /-
  2  Copyright (c) 2017 Microsoft Corporation. All rights reserved.
  3  Released under Apache 2.0 license as described in the file LICENSE.
  4  Author: Mario Carneiro
  5  -/
  6  import data.seq.seq data.seq.computation data.list.basic data.dlist
src         └──────────┘ └──────────────────┘ └─────────────┘ └────────┘
  7  universes u v w
  8  
  9  /-
 10  coinductive wseq (α : Type u) : Type u
 11  | nil : wseq α
 12  | cons : α → wseq α → wseq α
 13  | think : wseq α → wseq α
 14  -/
 15  
 16  /-- Weak sequences.
 17  
 18    While the `seq` structure allows for lists which may not be finite,
 19    a weak sequence also allows the computation of each element to
 20    involve an indeterminate amount of computation, including possibly
 21    an infinite loop. This is represented as a regular `seq` interspersed
 22    with `none` elements to indicate that computation is ongoing.
 23  
 24    This model is appropriate for Haskell style lazy lists, and is closed
 25    under most interesting computation patterns on infinite lists,
 26    but conversely it is difficult to extract elements from it. -/
 27  def wseq (α) := seq (option α)
id                   └─┘  └────┘ 
src                  └─┘  └────┘
typ                  └─┘  └────┘ 
doc                  └─┘
 28  
 29  namespace wseq
 30  variables {α : Type u} {β : Type v} {γ : Type w}
 31  
 32  /-- Turn a sequence into a weak sequence -/
 33  def of_seq : seq α → wseq α := (<$>) some
id                └─┘    └──┘          └──┘
src               └─┘     └──┘           └──┘
typ               └─┘    └──┘          └──┘
doc               └─┘     └──┘
 34  
 35  /-- Turn a list into a weak sequence -/
 36  def of_list (l : list α) : wseq α := of_seq l
id                    └──┘     └──┘     └────┘ 
src                   └──┘      └──┘      └────┘
typ                   └──┘     └──┘     └────┘ 
doc                             └──┘      └────┘
 37  
 38  /-- Turn a stream into a weak sequence -/
 39  def of_stream (l : stream α) : wseq α := of_seq l
id                      └────┘     └──┘     └────┘ 
src                     └────┘      └──┘      └────┘
typ                     └────┘     └──┘     └────┘ 
doc                                 └──┘      └────┘
 40  
 41  instance coe_seq : has_coe (seq α) (wseq α) := ⟨of_seq⟩
id                      └─────┘  └─┘    └──┘       └────┘
src                     └─────┘  └─┘     └──┘        └────┘
typ                     └─────┘  └─┘    └──┘       └────┘
doc                              └─┘     └──┘        └────┘
 42  instance coe_list : has_coe (list α) (wseq α) := ⟨of_list⟩
id                       └─────┘  └──┘    └──┘       └─────┘
src                      └─────┘  └──┘     └──┘        └─────┘
typ                      └─────┘  └──┘    └──┘       └─────┘
doc                                        └──┘        └─────┘
 43  instance coe_stream : has_coe (stream α) (wseq α) := ⟨of_stream⟩
id                         └─────┘  └────┘    └──┘       └───────┘
src                        └─────┘  └────┘     └──┘        └───────┘
typ                        └─────┘  └────┘    └──┘       └───────┘
doc                                            └──┘        └───────┘
 44  
 45  /-- The empty weak sequence -/
 46  def nil : wseq α := seq.nil
id             └──┘     └─────┘
src            └──┘      └─────┘
typ            └──┘     └─────┘
doc            └──┘      └─────┘
 47  
 48  instance : inhabited (wseq α) := ⟨nil⟩
id              └───────┘  └──┘       └─┘
src             └───────┘  └──┘        └─┘
typ             └───────┘  └──┘       └─┘
doc                        └──┘        └─┘
 49  
 50  /-- Prepend an element to a weak sequence -/
 51  def cons (a : α) : wseq α → wseq α := seq.cons (some a)
id                     └──┘    └──┘     └──────┘  └──┘ 
src                     └──┘     └──┘      └──────┘  └──┘
typ                    └──┘    └──┘     └──────┘  └──┘ 
doc                     └──┘     └──┘      └──────┘
 52  
 53  /-- Compute for one tick, without producing any elements -/
 54  def think : wseq α → wseq α := seq.cons none
id               └──┘    └──┘     └──────┘ └──┘
src              └──┘     └──┘      └──────┘ └──┘
typ              └──┘    └──┘     └──────┘ └──┘
doc              └──┘     └──┘      └──────┘
 55  
 56  /-- Destruct a weak sequence, to (eventually possibly) produce either
 57    `none` for `nil` or `some (a, s)` if an element is produced. -/
 58  def destruct : wseq α → computation (option (α × wseq α)) :=
id                  └──┘    └─────────┘  └────┘    └──┘ 
src                 └──┘     └─────────┘  └────┘     └──┘
typ                 └──┘    └─────────┘  └────┘    └──┘ 
doc                 └──┘     └─────────┘              └──┘
 59  computation.corec (λs, match seq.destruct s with
id   └───────────────┘           └──────────┘ 
src  └───────────────┘            └──────────┘
typ  └───────────────┘           └──────────┘ 
doc  └───────────────┘            └──────────┘
 60    | none              := sum.inl none
id       └──┘                 └─────┘ └──┘
src      └──┘                 └─────┘ └──┘
typ      └──┘                 └─────┘ └──┘
 61    | some (none, s')   := sum.inr s'
id       └──┘ └──┘  └┘       └─────┘
src      └──┘ └──┘           └─────┘
typ      └──┘ └──┘  └┘       └─────┘
 62    | some (some a, s') := sum.inl (some (a, s'))
id            └──┘   └┘     └─────┘  └──┘ 
src           └──┘           └─────┘  └──┘ 
typ           └──┘   └┘     └─────┘  └──┘ 
 63    end)
 64  
 65  def cases_on {C : wseq α → Sort v} (s : wseq α) (h1 : C nil)
id                     └──┘                 └──┘          └─┘
src                    └──┘                  └──┘            └─┘
typ                    └──┘                 └──┘          └─┘
doc                    └──┘                  └──┘            └─┘
 66    (h2 : ∀ x s, C (cons x s)) (h3 : ∀ s, C (think s)) : C s :=
id                  └──┘                 └───┘       
src                    └──┘                     └───┘
typ                 └──┘                 └───┘       
doc                    └──┘                     └───┘
 67  seq.cases_on s h1 (λ o, option.cases_on o h3 h2)
id   └──────────┘  └┘      └─────────────┘  └┘ └┘
src  └──────────┘            └─────────────┘
typ  └──────────┘  └┘      └─────────────┘  └┘ └┘
 68  
 69  protected def mem (a : α) (s : wseq α) := seq.mem (some a) s
id                                 └──┘      └─────┘  └──┘   
src                                 └──┘       └─────┘  └──┘
typ                                └──┘      └─────┘  └──┘   
doc                                 └──┘
 70  
 71  instance : has_mem α (wseq α) :=
id              └─────┘   └──┘ 
src             └─────┘    └──┘
typ             └─────┘   └──┘ 
doc                        └──┘
 72  ⟨wseq.mem⟩
id    └──────┘
src   └──────┘
typ   └──────┘
 73  
 74  theorem not_mem_nil (a : α) : a ∉ @nil α := seq.not_mem_nil a
id                                   └─┘     └─────────────┘ 
src                                    └─┘      └─────────────┘
typ                                  └─┘     └─────────────┘ 
doc                                     └─┘
 75  
 76  /-- Get the head of a weak sequence. This involves a possibly
 77    infinite computation. -/
 78  def head (s : wseq α) : computation (option α) :=
id                 └──┘     └─────────┘  └────┘ 
src                └──┘      └─────────┘  └────┘
typ                └──┘     └─────────┘  └────┘ 
doc                └──┘      └─────────┘
 79  computation.map ((<$>) prod.fst) (destruct s)
id   └─────────────┘       └──────┘   └──────┘ 
src  └─────────────┘       └──────┘   └──────┘
typ  └─────────────┘       └──────┘   └──────┘ 
doc  └─────────────┘                   └──────┘
 80  
 81  /-- Encode a computation yielding a weak sequence into additional
 82    `think` constructors in a weak sequence -/
 83  def flatten : computation (wseq α) → wseq α :=
id                 └─────────┘  └──┘     └──┘ 
src                └─────────┘  └──┘      └──┘
typ                └─────────┘  └──┘     └──┘ 
doc                └─────────┘  └──┘      └──┘
 84  seq.corec (λc, match computation.destruct c with
id   └───────┘           └──────────────────┘ 
src  └───────┘            └──────────────────┘
typ  └───────┘           └──────────────────┘ 
doc  └───────┘            └──────────────────┘
 85    | sum.inl s := seq.omap return (seq.destruct s)
id       └─────┘     └──────┘ └────┘  └──────────┘
src      └─────┘      └──────┘ └────┘  └──────────┘
typ      └─────┘     └──────┘ └────┘  └──────────┘
doc                   └──────┘         └──────────┘
 86    | sum.inr c' := some (none, c')
id       └─────┘ └┘    └──┘ └──┘
src      └─────┘       └──┘ └──┘
typ      └─────┘ └┘    └──┘ └──┘
 87    end)
 88  
 89  /-- Get the tail of a weak sequence. This doesn't need a `computation`
 90    wrapper, unlike `head`, because `flatten` allows us to hide this
 91    in the construction of the weak sequence itself. -/
 92  def tail (s : wseq α) : wseq α :=
id                 └──┘     └──┘ 
src                └──┘      └──┘
typ                └──┘     └──┘ 
doc                └──┘      └──┘
 93  flatten $ (λo, option.rec_on o nil prod.snd) <$> destruct s
id   └─────┘       └───────────┘  └─┘ └──────┘  └─┘ └──────┘ 
src  └─────┘        └───────────┘   └─┘ └──────┘  └─┘ └──────┘
typ  └─────┘       └───────────┘  └─┘ └──────┘  └─┘ └──────┘ 
doc  └─────┘                        └─┘               └──────┘
 94  
 95  /-- drop the first `n` elements from `s`. -/
 96  def drop (s : wseq α) : ℕ → wseq α
id                 └──┘       └──┘ 
src                └──┘         └──┘
typ                └──┘       └──┘ 
doc                └──┘          └──┘
 97  | 0     := s
id              
typ             
 98  | (n+1) := tail (drop n)
id            └──┘  └──┘
src            └──┘
typ           └──┘  └──┘
doc             └──┘
 99  attribute [simp] drop
id                    └──┘
src                   └──┘
typ                   └──┘
doc             └──┘  └──┘
100  
101  /-- Get the nth element of `s`. -/
102  def nth (s : wseq α) (n : ℕ) : computation (option α) := head (drop s n)
id                └──┘            └─────────┘  └────┘      └──┘  └──┘  
src               └──┘             └─────────┘  └────┘       └──┘  └──┘
typ               └──┘            └─────────┘  └────┘      └──┘  └──┘  
doc               └──┘              └─────────┘               └──┘  └──┘
103  
104  /-- Convert `s` to a list (if it is finite and completes in finite time). -/
105  def to_list (s : wseq α) : computation (list α) :=
id                    └──┘     └─────────┘  └──┘ 
src                   └──┘      └─────────┘  └──┘
typ                   └──┘     └─────────┘  └──┘ 
doc                   └──┘      └─────────┘
106  @computation.corec (list α) (list α × wseq α) (λ⟨l, s⟩,
id    └───────────────┘  └──┘    └──┘   └──┘       
src   └───────────────┘  └──┘     └──┘    └──┘
typ   └───────────────┘  └──┘    └──┘   └──┘       
doc   └───────────────┘                    └──┘
107    match seq.destruct s with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
108    | none              := sum.inl l.reverse
id       └──┘                 └─────┘  └──────┘
src      └──┘                 └─────┘  └──────┘
typ      └──┘                 └─────┘  └──────┘
109    | some (none, s')   := sum.inr (l, s')
id       └──┘ └──┘  └┘       └─────┘ 
src      └──┘ └──┘           └─────┘ 
typ      └──┘ └──┘  └┘       └─────┘ 
110    | some (some a, s') := sum.inr (a::l, s')
id            └──┘   └┘     └─────┘  └┘
src           └──┘           └─────┘  └┘
typ           └──┘   └┘     └─────┘  └┘
111    end) ([], s)
id          └┘  
src         └┘
typ         └┘  
112  
113  /-- Get the length of `s` (if it is finite and completes in finite time). -/
114  def length (s : wseq α) : computation ℕ :=
id                   └──┘     └─────────┘ 
src                  └──┘      └─────────┘ 
typ                  └──┘     └─────────┘ 
doc                  └──┘      └─────────┘
115  @computation.corec ℕ (ℕ × wseq α) (λ⟨n, s⟩,
id    └───────────────┘     └──┘       
src   └───────────────┘     └──┘
typ   └───────────────┘     └──┘       
doc   └───────────────┘        └──┘
116    match seq.destruct s with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
117    | none              := sum.inl n
id       └──┘                 └─────┘
src      └──┘                 └─────┘
typ      └──┘                 └─────┘
118    | some (none, s')   := sum.inr (n, s')
id       └──┘ └──┘  └┘       └─────┘ 
src      └──┘ └──┘           └─────┘ 
typ      └──┘ └──┘  └┘       └─────┘ 
119    | some (some a, s') := sum.inr (n+1, s')
id            └──┘    └┘     └─────┘  
src           └──┘           └─────┘  
typ           └──┘    └┘     └─────┘  
120    end) (0, s)
id             
src         
typ            
121  
122  /-- A weak sequence is finite if `to_list s` terminates. Equivalently,
123    it is a finite number of `think` and `cons` applied to `nil`. -/
124  @[class] def is_finite (s : wseq α) : Prop := (to_list s).terminates
id                               └──┘              └─────┘  └────────┘
src                              └──┘               └─────┘   └────────┘
typ                              └──┘              └─────┘  └────────┘
doc                              └──┘               └─────┘   └────────┘
125  
126  instance to_list_terminates (s : wseq α) [h : is_finite s] : (to_list s).terminates := h
id                                    └──┘        └───────┘      └─────┘  └────────┘     
src                                   └──┘         └───────┘       └─────┘   └────────┘
typ                                   └──┘        └───────┘      └─────┘  └────────┘     
doc                                   └──┘         └───────┘       └─────┘   └────────┘
127  
128  /-- Get the list corresponding to a finite weak sequence. -/
129  def get (s : wseq α) [is_finite s] : list α := (to_list s).get
id                └──┘    └───────┘     └──┘      └─────┘  └─┘
src               └──┘     └───────┘      └──┘       └─────┘   └─┘
typ               └──┘    └───────┘     └──┘      └─────┘  └─┘
doc               └──┘     └───────┘                 └─────┘   └─┘
130  
131  /-- A weak sequence is *productive* if it never stalls forever - there are
132   always a finite number of `think`s between `cons` constructors.
133   The sequence itself is allowed to be infinite though. -/
134  @[class] def productive (s : wseq α) : Prop := ∀ n, (nth s n).terminates
id                                └──┘                  └─┘   └────────┘
src                               └──┘                    └─┘     └────────┘
typ                               └──┘                  └─┘   └────────┘
doc                               └──┘                    └─┘     └────────┘
135  
136  instance nth_terminates (s : wseq α) [h : productive s] : ∀ n, (nth s n).terminates := h
id                                └──┘        └────────┘          └─┘   └────────┘     
src                               └──┘         └────────┘            └─┘     └────────┘
typ                               └──┘        └────────┘          └─┘   └────────┘     
doc                               └──┘         └────────┘            └─┘     └────────┘
137  
138  instance head_terminates (s : wseq α) [h : productive s] : (head s).terminates := h 0
id                                 └──┘        └────────┘      └──┘  └────────┘     
src                                └──┘         └────────┘       └──┘   └────────┘
typ                                └──┘        └────────┘      └──┘  └────────┘     
doc                                └──┘         └────────┘       └──┘   └────────┘
139  
140  /-- Replace the `n`th element of `s` with `a`. -/
141  def update_nth (s : wseq α) (n : ℕ) (a : α) : wseq α :=
id                       └──┘                   └──┘ 
src                      └──┘                     └──┘
typ                      └──┘                   └──┘ 
doc                      └──┘                      └──┘
142  @seq.corec (option α) (ℕ × wseq α) (λ⟨n, s⟩,
id    └───────┘  └────┘      └──┘       
src   └───────┘  └────┘       └──┘
typ   └───────┘  └────┘      └──┘       
doc   └───────┘                 └──┘
143    match seq.destruct s, n with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
144    | none,               n     := none
id       └──┘                         └──┘
src      └──┘                         └──┘
typ      └──┘                         └──┘
145    | some (none, s'),    n     := some (none, n, s')
id       └──┘ └──┘  └┘              └──┘ └──┘
src      └──┘ └──┘                   └──┘ └──┘
typ      └──┘ └──┘  └┘              └──┘ └──┘
146    | some (some a', s'), 0     := some (some a', 0, s')
id            └──┘ └┘  └┘            └──┘ └──┘
src           └──┘                   └──┘ └──┘
typ           └──┘ └┘  └┘            └──┘ └──┘
147    | some (some a', s'), 1     := some (some a, 0, s')
id            └──┘     └┘            └──┘ └──┘ 
src           └──┘                   └──┘ └──┘
typ           └──┘     └┘            └──┘ └──┘ 
148    | some (some a', s'), (n+2) := some (some a', n+1, s')
id            └──┘ └┘  └┘          └──┘ └──┘      
src           └──┘                  └──┘ └──┘      
typ           └──┘ └┘  └┘          └──┘ └──┘      
149    end) (n+1, s)
id             
src          
typ            
150  
151  /-- Remove the `n`th element of `s`. -/
152  def remove_nth (s : wseq α) (n : ℕ) : wseq α :=
id                       └──┘            └──┘ 
src                      └──┘             └──┘
typ                      └──┘            └──┘ 
doc                      └──┘              └──┘
153  @seq.corec (option α) (ℕ × wseq α) (λ⟨n, s⟩,
id    └───────┘  └────┘      └──┘       
src   └───────┘  └────┘       └──┘
typ   └───────┘  └────┘      └──┘       
doc   └───────┘                 └──┘
154    match seq.destruct s, n with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
155    | none,               n     := none
id       └──┘                         └──┘
src      └──┘                         └──┘
typ      └──┘                         └──┘
156    | some (none, s'),    n     := some (none, n, s')
id       └──┘ └──┘  └┘              └──┘ └──┘
src      └──┘ └──┘                   └──┘ └──┘
typ      └──┘ └──┘  └┘              └──┘ └──┘
157    | some (some a', s'), 0     := some (some a', 0, s')
id            └──┘ └┘  └┘            └──┘ └──┘
src           └──┘                   └──┘ └──┘
typ           └──┘ └┘  └┘            └──┘ └──┘
158    | some (some a', s'), 1     := some (none, 0, s')
id            └──┘     └┘            └──┘ └──┘
src           └──┘                   └──┘ └──┘
typ           └──┘     └┘            └──┘ └──┘
159    | some (some a', s'), (n+2) := some (some a', n+1, s')
id            └──┘ └┘  └┘          └──┘ └──┘      
src           └──┘                  └──┘ └──┘      
typ           └──┘ └┘  └┘          └──┘ └──┘      
160    end) (n+1, s)
id             
src          
typ            
161  
162  /-- Map the elements of `s` over `f`, removing any values that yield `none`. -/
163  def filter_map (f : α → option β) : wseq α → wseq β :=
id                          └────┘     └──┘    └──┘ 
src                          └────┘      └──┘     └──┘
typ                         └────┘     └──┘    └──┘ 
doc                                      └──┘     └──┘
164  seq.corec (λs, match seq.destruct s with
id   └───────┘           └──────────┘ 
src  └───────┘            └──────────┘
typ  └───────┘           └──────────┘ 
doc  └───────┘            └──────────┘
165    | none              := none
id       └──┘                 └──┘
src      └──┘                 └──┘
typ      └──┘                 └──┘
166    | some (none, s')   := some (none, s')
id       └──┘ └──┘  └┘       └──┘ └──┘
src      └──┘ └──┘           └──┘ └──┘
typ      └──┘ └──┘  └┘       └──┘ └──┘
167    | some (some a, s') := some (f a, s')
id            └──┘   └┘     └──┘ 
src           └──┘           └──┘ 
typ           └──┘   └┘     └──┘ 
168    end)
169  
170  /-- Select the elements of `s` that satisfy `p`. -/
171  def filter (p : α → Prop) [decidable_pred p] : wseq α → wseq α :=
id                             └────────────┘     └──┘    └──┘ 
src                             └────────────┘      └──┘     └──┘
typ                            └────────────┘     └──┘    └──┘ 
doc                                                 └──┘     └──┘
172  filter_map (λa, if p a then some a else none)
id   └────────┘               └──┘       └──┘
src  └────────┘                  └──┘        └──┘
typ  └────────┘               └──┘       └──┘
doc  └────────┘
173  
174  -- example of infinite list manipulations
175  /-- Get the first element of `s` satisfying `p`. -/
176  def find (p : α → Prop) [decidable_pred p] (s : wseq α) : computation (option α) :=
id                           └────────────┘        └──┘     └─────────┘  └────┘ 
src                           └────────────┘         └──┘      └─────────┘  └────┘
typ                          └────────────┘        └──┘     └─────────┘  └────┘ 
doc                                                  └──┘      └─────────┘
177  head $ filter p s
id   └──┘   └────┘  
src  └──┘   └────┘
typ  └──┘   └────┘  
doc  └──┘   └────┘
178  
179  /-- Zip a function over two weak sequences -/
180  def zip_with (f : α → β → γ) (s1 : wseq α) (s2 : wseq β) : wseq γ :=
id                                   └──┘         └──┘     └──┘ 
src                                     └──┘          └──┘      └──┘
typ                                  └──┘         └──┘     └──┘ 
doc                                     └──┘          └──┘      └──┘
181  @seq.corec (option γ) (wseq α × wseq β) (λ⟨s1, s2⟩,
id    └───────┘  └────┘    └──┘   └──┘     └┘  └┘
src   └───────┘  └────┘     └──┘    └──┘
typ   └───────┘  └────┘    └──┘   └──┘     └┘  └┘
doc   └───────┘             └──┘     └──┘
182    match seq.destruct s1, seq.destruct s2 with
id           └──────────┘     └──────────┘
src          └──────────┘     └──────────┘
typ          └──────────┘     └──────────┘
doc          └──────────┘     └──────────┘
183    | some (none, s1'),    some (none, s2')    := some (none, s1', s2')
id                  └─┘      └──┘ └──┘  └─┘        └──┘ └──┘
src                          └──┘ └──┘             └──┘ └──┘
typ                 └─┘      └──┘ └──┘  └─┘        └──┘ └──┘
184    | some (some a1, s1'), some (none, s2')    := some (none, s1, s2')
id                           └──┘ └──┘  └─┘        └──┘ └──┘
src                          └──┘ └──┘             └──┘ └──┘
typ                          └──┘ └──┘  └─┘        └──┘ └──┘
185    | some (none, s1'),    some (some a2, s2') := some (none, s1', s2)
id            └──┘  └─┘           └──┘             └──┘ └──┘
src           └──┘                └──┘             └──┘ └──┘
typ           └──┘  └─┘           └──┘             └──┘ └──┘
186    | some (some a1, s1'), some (some a2, s2') := some (some (f a1 a2), s1', s2')
id                 └┘  └─┘        └──┘ └┘  └─┘     └──┘ └──┘  
src                               └──┘             └──┘ └──┘
typ                └┘  └─┘        └──┘ └┘  └─┘     └──┘ └──┘  
187    | _,                   _                   := none
id                                                   └──┘
src                                                  └──┘
typ                                                  └──┘
188    end) (s1, s2)
id          └┘  └┘
src         
typ         └┘  └┘
189  
190  /-- Zip two weak sequences into a single sequence of pairs -/
191  def zip : wseq α → wseq β → wseq (α × β) := zip_with prod.mk
id             └──┘    └──┘    └──┘         └──────┘ └─────┘
src            └──┘     └──┘     └──┘           └──────┘ └─────┘
typ            └──┘    └──┘    └──┘         └──────┘ └─────┘
doc            └──┘     └──┘     └──┘            └──────┘
192  
193  /-- Get the list of indexes of elements of `s` satisfying `p` -/
194  def find_indexes (p : α → Prop) [decidable_pred p] (s : wseq α) : wseq ℕ :=
id                                   └────────────┘        └──┘     └──┘ 
src                                   └────────────┘         └──┘      └──┘ 
typ                                  └────────────┘        └──┘     └──┘ 
doc                                                          └──┘      └──┘
195  (zip s (stream.nats : wseq ℕ)).filter_map
id    └─┘   └─────────┘   └──┘   └────────┘
src   └─┘    └─────────┘   └──┘   └────────┘
typ   └─┘   └─────────┘   └──┘   └────────┘
doc   └─┘                  └──┘    └────────┘
196    (λ ⟨a, n⟩, if p a then some n else none)
id                        └──┘        └──┘
src                           └──┘        └──┘
typ                       └──┘        └──┘
197  
198  /-- Get the index of the first element of `s` satisfying `p` -/
199  def find_index (p : α → Prop) [decidable_pred p] (s : wseq α) : computation ℕ :=
id                                 └────────────┘        └──┘     └─────────┘ 
src                                 └────────────┘         └──┘      └─────────┘ 
typ                                └────────────┘        └──┘     └─────────┘ 
doc                                                        └──┘      └─────────┘
200  (λ o, option.get_or_else o 0) <$> head (find_indexes p s)
id        └────────────────┘     └─┘ └──┘  └──────────┘  
src        └────────────────┘      └─┘ └──┘  └──────────┘
typ       └────────────────┘     └─┘ └──┘  └──────────┘  
doc                                    └──┘  └──────────┘
201  
202  /-- Get the index of the first occurrence of `a` in `s` -/
203  def index_of [decidable_eq α] (a : α) : wseq α → computation ℕ := find_index (eq a)
id                 └──────────┘            └──┘    └─────────┘     └────────┘  └┘ 
src                └──────────┘              └──┘     └─────────┘     └────────┘  └┘
typ                └──────────┘            └──┘    └─────────┘     └────────┘  └┘ 
doc                                          └──┘     └─────────┘      └────────┘
204  
205  /-- Get the indexes of occurrences of `a` in `s` -/
206  def indexes_of [decidable_eq α] (a : α) : wseq α → wseq ℕ := find_indexes (eq a)
id                   └──────────┘            └──┘    └──┘     └──────────┘  └┘ 
src                  └──────────┘              └──┘     └──┘     └──────────┘  └┘
typ                  └──────────┘            └──┘    └──┘     └──────────┘  └┘ 
doc                                            └──┘     └──┘      └──────────┘
207  
208  /-- `union s1 s2` is a weak sequence which interleaves `s1` and `s2` in
209    some order (nondeterministically). -/
210  def union (s1 s2 : wseq α) : wseq α :=
id                      └──┘     └──┘ 
src                     └──┘      └──┘
typ                     └──┘     └──┘ 
doc                     └──┘      └──┘
211  @seq.corec (option α) (wseq α × wseq α) (λ⟨s1, s2⟩,
id    └───────┘  └────┘    └──┘   └──┘     └┘  └┘
src   └───────┘  └────┘     └──┘    └──┘
typ   └───────┘  └────┘    └──┘   └──┘     └┘  └┘
doc   └───────┘             └──┘     └──┘
212    match seq.destruct s1, seq.destruct s2 with
id           └──────────┘     └──────────┘
src          └──────────┘     └──────────┘
typ          └──────────┘     └──────────┘
doc          └──────────┘     └──────────┘
213    | none,                none                := none
id                            └──┘                   └──┘
src                           └──┘                   └──┘
typ                           └──┘                   └──┘
214    | some (a1, s1'),      none                := some (a1, s1', nil)
id       └──┘ └┘  └─┘        └──┘                   └──┘          └─┘
src      └──┘                └──┘                   └──┘          └─┘
typ      └──┘ └┘  └─┘        └──┘                   └──┘          └─┘
doc                                                                 └─┘
215    | none,                some (a2, s2')      := some (a2, nil, s2')
id       └──┘                 └──┘ └┘  └─┘          └──┘     └─┘
src      └──┘                 └──┘                  └──┘     └─┘
typ      └──┘                 └──┘ └┘  └─┘          └──┘     └─┘
doc                                                            └─┘
216    | some (none, s1'),    some (none, s2')    := some (none, s1', s2')
id                  └─┘      └──┘ └──┘  └─┘        └──┘ └──┘
src                          └──┘ └──┘             └──┘ └──┘
typ                 └─┘      └──┘ └──┘  └─┘        └──┘ └──┘
217    | some (some a1, s1'), some (none, s2')    := some (some a1, s1', s2')
id                 └┘  └─┘   └──┘ └──┘  └─┘        └──┘ └──┘
src                          └──┘ └──┘             └──┘ └──┘
typ                └┘  └─┘   └──┘ └──┘  └─┘        └──┘ └──┘
218    | some (none, s1'),    some (some a2, s2') := some (some a2, s1', s2')
id            └──┘  └─┘           └──┘ └┘  └─┘     └──┘ └──┘
src           └──┘                └──┘             └──┘ └──┘
typ           └──┘  └─┘           └──┘ └┘  └─┘     └──┘ └──┘
219    | some (some a1, s1'), some (some a2, s2') := some (some a1, cons a2 s1', s2')
id                 └┘  └─┘        └──┘ └┘  └─┘     └──┘ └──┘     └──┘
src                               └──┘             └──┘ └──┘     └──┘
typ                └┘  └─┘        └──┘ └┘  └─┘     └──┘ └──┘     └──┘
doc                                                                 └──┘
220    end) (s1, s2)
id          └┘  └┘
src         
typ         └┘  └┘
221  
222  /-- Returns `tt` if `s` is `nil` and `ff` if `s` has an element -/
223  def is_empty (s : wseq α) : computation bool :=
id                     └──┘     └─────────┘ └──┘
src                    └──┘      └─────────┘ └──┘
typ                    └──┘     └─────────┘ └──┘
doc                    └──┘      └─────────┘
224  computation.map option.is_none $ head s
id   └─────────────┘ └────────────┘   └──┘ 
src  └─────────────┘ └────────────┘   └──┘
typ  └─────────────┘ └────────────┘   └──┘ 
doc  └─────────────┘                  └──┘
225  
226  /-- Calculate one step of computation -/
227  def compute (s : wseq α) : wseq α :=
id                    └──┘     └──┘ 
src                   └──┘      └──┘
typ                   └──┘     └──┘ 
doc                   └──┘      └──┘
228  match seq.destruct s with
id         └──────────┘ 
src        └──────────┘
typ        └──────────┘ 
doc        └──────────┘
229  | some (none, s') := s'
id     └──┘ └──┘  └┘
src    └──┘ └──┘
typ    └──┘ └──┘  └┘
230  | _               := s
id                        
typ                       
231  end
232  
233  /-- Get the first `n` elements of a weak sequence -/
234  def take (s : wseq α) (n : ℕ) : wseq α :=
id                 └──┘            └──┘ 
src                └──┘             └──┘
typ                └──┘            └──┘ 
doc                └──┘              └──┘
235  @seq.corec (option α) (ℕ × wseq α) (λ⟨n, s⟩,
id    └───────┘  └────┘      └──┘       
src   └───────┘  └────┘       └──┘
typ   └───────┘  └────┘      └──┘       
doc   └───────┘                 └──┘
236    match n, seq.destruct s with
id              └──────────┘
src             └──────────┘
typ             └──────────┘
doc             └──────────┘
237    | 0,   _                 := none
id                                 └──┘
src                                └──┘
typ                                └──┘
238    | m+1, none              := none
id           └──┘                 └──┘
src          └──┘                 └──┘
typ          └──┘                 └──┘
239    | m+1, some (none, s')   := some (none, m+1, s')
id          └──┘ └──┘  └┘       └──┘ └──┘   
src          └──┘ └──┘           └──┘ └──┘   
typ         └──┘ └──┘  └┘       └──┘ └──┘   
240    | m+1, some (some a, s') := some (some a, m, s')
id               └──┘   └┘     └──┘ └──┘
src               └──┘           └──┘ └──┘
typ              └──┘   └┘     └──┘ └──┘
241    end) (n, s)
id            
src         
typ           
242  
243  /-- Split the sequence at position `n` into a finite initial segment
244    and the weak sequence tail -/
245  def split_at (s : wseq α) (n : ℕ) : computation (list α × wseq α) :=
id                     └──┘            └─────────┘  └──┘   └──┘ 
src                    └──┘             └─────────┘  └──┘    └──┘
typ                    └──┘            └─────────┘  └──┘   └──┘ 
doc                    └──┘              └─────────┘           └──┘
246  @computation.corec (list α × wseq α) (ℕ × list α × wseq α) (λ⟨n, l, s⟩,
id    └───────────────┘  └──┘   └──┘      └──┘   └──┘         
src   └───────────────┘  └──┘    └──┘       └──┘    └──┘
typ   └───────────────┘  └──┘   └──┘      └──┘   └──┘         
doc   └───────────────┘           └──┘                  └──┘
247    match n, seq.destruct s with
id              └──────────┘
src             └──────────┘
typ             └──────────┘
doc             └──────────┘
248    | 0,   _                 := sum.inl (l.reverse, s)
id                                 └─────┘  └──────┘
src                                └─────┘  └──────┘
typ                                └─────┘  └──────┘
249    | m+1, none              := sum.inl (l.reverse, s)
id           └──┘                 └─────┘  └──────┘
src          └──┘                 └─────┘  └──────┘
typ          └──┘                 └─────┘  └──────┘
250    | m+1, some (none, s')   := sum.inr (n, l, s')
id           └──┘ └──┘  └┘       └─────┘ 
src          └──┘ └──┘           └─────┘ 
typ          └──┘ └──┘  └┘       └─────┘ 
251    | m+1, some (some a, s') := sum.inr (m, a::l, s')
id               └──┘   └┘     └─────┘     └┘
src               └──┘           └─────┘     └┘
typ              └──┘   └┘     └─────┘     └┘
252    end) (n, [], s)
id            └┘  
src            └┘
typ           └┘  
253  
254  /-- Returns `tt` if any element of `s` satisfies `p` -/
255  def any (s : wseq α) (p : α → bool) : computation bool :=
id                └──┘           └──┘    └─────────┘ └──┘
src               └──┘             └──┘    └─────────┘ └──┘
typ               └──┘           └──┘    └─────────┘ └──┘
doc               └──┘                     └─────────┘
256  computation.corec (λs : wseq α,
id   └───────────────┘       └──┘ 
src  └───────────────┘       └──┘
typ  └───────────────┘       └──┘ 
doc  └───────────────┘       └──┘
257    match seq.destruct s with
id           └──────────┘ 
src          └──────────┘
typ          └──────────┘ 
doc          └──────────┘
258    | none              := sum.inl ff
id       └──┘                 └─────┘ └┘
src      └──┘                 └─────┘ └┘
typ      └──┘                 └─────┘ └┘
259    | some (none, s')   := sum.inr s'
id       └──┘ └──┘  └┘       └─────┘
src      └──┘ └──┘           └─────┘
typ      └──┘ └──┘  └┘       └─────┘
260    | some (some a, s') := if p a then sum.inl tt else sum.inr s'
id            └──┘   └┘                └─────┘ └┘      └─────┘
src           └──┘                       └─────┘ └┘      └─────┘
typ           └──┘   └┘                └─────┘ └┘      └─────┘
261    end) s
id          
typ         
262  
263  /-- Returns `tt` if every element of `s` satisfies `p` -/
264  def all (s : wseq α) (p : α → bool) : computation bool :=
id                └──┘           └──┘    └─────────┘ └──┘
src               └──┘             └──┘    └─────────┘ └──┘
typ               └──┘           └──┘    └─────────┘ └──┘
doc               └──┘                     └─────────┘
265  computation.corec (λs : wseq α,
id   └───────────────┘       └──┘ 
src  └───────────────┘       └──┘
typ  └───────────────┘       └──┘ 
doc  └───────────────┘       └──┘
266    match seq.destruct s with
id           └──────────┘ 
src          └──────────┘
typ          └──────────┘ 
doc          └──────────┘
267    | none              := sum.inl tt
id       └──┘                 └─────┘ └┘
src      └──┘                 └─────┘ └┘
typ      └──┘                 └─────┘ └┘
268    | some (none, s')   := sum.inr s'
id       └──┘ └──┘  └┘       └─────┘
src      └──┘ └──┘           └─────┘
typ      └──┘ └──┘  └┘       └─────┘
269    | some (some a, s') := if p a then sum.inr s' else sum.inl ff
id            └──┘   └┘                └─────┘         └─────┘ └┘
src           └──┘                       └─────┘         └─────┘ └┘
typ           └──┘   └┘                └─────┘         └─────┘ └┘
270    end) s
id          
typ         
271  
272  /-- Apply a function to the elements of the sequence to produce a sequence
273    of partial results. (There is no `scanr` because this would require
274    working from the end of the sequence, which may not exist.) -/
275  def scanl (f : α → β → α) (a : α) (s : wseq β) : wseq α :=
id                                      └──┘     └──┘ 
src                                         └──┘      └──┘
typ                                     └──┘     └──┘ 
doc                                         └──┘      └──┘
276  cons a $ @seq.corec (option α) (α × wseq β) (λ⟨a, s⟩,
id   └──┘     └───────┘  └────┘      └──┘       
src  └──┘      └───────┘  └────┘        └──┘
typ  └──┘     └───────┘  └────┘      └──┘       
doc  └──┘      └───────┘                 └──┘
277    match seq.destruct s with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
278    | none              := none
id       └──┘                 └──┘
src      └──┘                 └──┘
typ      └──┘                 └──┘
279    | some (none, s')   := some (none, a, s')
id       └──┘ └──┘  └┘       └──┘ └──┘
src      └──┘ └──┘           └──┘ └──┘
typ      └──┘ └──┘  └┘       └──┘ └──┘
280    | some (some b, s') := let a' := f a b in some (some a', a', s')
id            └──┘   └┘         └┘            └──┘ └──┘ └┘  └┘
src           └──┘                              └──┘ └──┘
typ           └──┘   └┘         └┘            └──┘ └──┘ └┘  └┘
281    end) (a, s)
id            
src         
typ           
282  
283  /-- Get the weak sequence of initial segments of the input sequence -/
284  def inits (s : wseq α) : wseq (list α) :=
id                  └──┘     └──┘  └──┘ 
src                 └──┘      └──┘  └──┘
typ                 └──┘     └──┘  └──┘ 
doc                 └──┘      └──┘
285  cons [] $ @seq.corec (option (list α)) (dlist α × wseq α) (λ ⟨l, s⟩,
id   └──┘ └┘    └───────┘  └────┘  └──┘     └───┘   └──┘        
src  └──┘ └┘    └───────┘  └────┘  └──┘      └───┘    └──┘
typ  └──┘ └┘    └───────┘  └────┘  └──┘     └───┘   └──┘        
doc  └──┘       └───────┘                    └───┘     └──┘
286    match seq.destruct s with
id           └──────────┘
src          └──────────┘
typ          └──────────┘
doc          └──────────┘
287    | none              := none
id       └──┘                 └──┘
src      └──┘                 └──┘
typ      └──┘                 └──┘
288    | some (none, s')   := some (none, l, s')
id       └──┘ └──┘  └┘       └──┘ └──┘
src      └──┘ └──┘           └──┘ └──┘
typ      └──┘ └──┘  └┘       └──┘ └──┘
289    | some (some a, s') := let l' := l.concat a in
id            └──┘   └┘         └┘     └─────┘
src           └──┘                      └─────┘
typ           └──┘   └┘         └┘     └─────┘
doc                                      └─────┘
290                           some (some l'.to_list, l', s')
id                            └──┘ └──┘ └┘└──────┘  └┘
src                           └──┘ └──┘   └──────┘
typ                           └──┘ └──┘ └┘└──────┘  └┘
doc                                        └──────┘
291    end) (dlist.empty, s)
id          └─────────┘  
src         └─────────┘
typ         └─────────┘  
doc          └─────────┘
292  
293  /-- Like take, but does not wait for a result. Calculates `n` steps of
294    computation and returns the sequence computed so far -/
295  def collect (s : wseq α) (n : ℕ) : list α :=
id                    └──┘            └──┘ 
src                   └──┘             └──┘
typ                   └──┘            └──┘ 
doc                   └──┘
296  (seq.take n s).filter_map id
id    └──────┘   └────────┘  └┘
src   └──────┘     └────────┘  └┘
typ   └──────┘   └────────┘  └┘
doc   └──────┘
297  
298  /-- Append two weak sequences. As with `seq.append`, this may not use
299    the second sequence if the first one takes forever to compute -/
300  def append : wseq α → wseq α → wseq α := seq.append
id                └──┘    └──┘    └──┘     └────────┘
src               └──┘     └──┘     └──┘      └────────┘
typ               └──┘    └──┘    └──┘     └────────┘
doc               └──┘     └──┘     └──┘      └────────┘
301  
302  /-- Map a function over a weak sequence -/
303  def map (f : α → β) : wseq α → wseq β := seq.map (option.map f)
id                       └──┘    └──┘     └─────┘  └────────┘ 
src                        └──┘     └──┘      └─────┘  └────────┘
typ                      └──┘    └──┘     └─────┘  └────────┘ 
doc                        └──┘     └──┘      └─────┘
304  
305  /-- Flatten a sequence of weak sequences. (Note that this allows
306    empty sequences, unlike `seq.join`.) -/
307  def join (S : wseq (wseq α)) : wseq α :=
id                 └──┘  └──┘      └──┘ 
src                └──┘  └──┘       └──┘
typ                └──┘  └──┘      └──┘ 
doc                └──┘  └──┘       └──┘
308  seq.join ((λo : option (wseq α), match o with
id   └──────┘        └────┘  └──┘          
src  └──────┘        └────┘  └──┘
typ  └──────┘        └────┘  └──┘          
doc  └──────┘                └──┘
309    | none := seq1.ret none
id       └──┘    └──────┘ └──┘
src      └──┘    └──────┘ └──┘
typ      └──┘    └──────┘ └──┘
doc              └──────┘
310    | some s := (none, s)
id       └──┘     └──┘
src      └──┘      └──┘
typ      └──┘     └──┘
311    end) <$> S)
id          └─┘ 
src         └─┘
typ         └─┘ 
312  
313  /-- Monadic bind operator for weak sequences -/
314  def bind (s : wseq α) (f : α → wseq β) : wseq β :=
id                 └──┘           └──┘     └──┘ 
src                └──┘             └──┘      └──┘
typ                └──┘           └──┘     └──┘ 
doc                └──┘             └──┘      └──┘
315  join (map f s)
id   └──┘  └─┘  
src  └──┘  └─┘
typ  └──┘  └─┘  
doc  └──┘  └─┘
316  
317  @[simp] def lift_rel_o (R : α → β → Prop) (C : wseq α → wseq β → Prop) :
id                                                └──┘    └──┘ 
src                                                 └──┘     └──┘
typ                                               └──┘    └──┘ 
doc    └──┘                                         └──┘     └──┘
318    option (α × wseq α) → option (β × wseq β) → Prop
id     └────┘    └──┘    └────┘    └──┘ 
src    └────┘     └──┘      └────┘     └──┘
typ    └────┘    └──┘    └────┘    └──┘ 
doc                └──┘                  └──┘
319  | none          none          := true
id                   └──┘             └──┘
src                  └──┘             └──┘
typ                  └──┘             └──┘
320  | (some (a, s)) (some (b, t)) := R a b ∧ C s t
id                 └──┘               
src                  └──┘                 
typ                └──┘               
321  | _             _             := false
id                                    └───┘
src                                   └───┘
typ                                   └───┘
322  
323  theorem lift_rel_o.imp {R S : α → β → Prop} {C D : wseq α → wseq β → Prop}
id                                                    └──┘    └──┘ 
src                                                     └──┘     └──┘
typ                                                   └──┘    └──┘ 
doc                                                     └──┘     └──┘
324    (H1 : ∀ a b, R a b → S a b) (H2 : ∀ s t, C s t → D s t) :
id                                           
typ                                          
325    ∀ {o p}, lift_rel_o R C o p → lift_rel_o S D o p
id           └────────┘       └────────┘    
src             └────────┘           └────────┘
typ          └────────┘       └────────┘    
326  | none          none          h := trivial
id                   └──┘               └─────┘
src                  └──┘               └─────┘
typ                  └──┘               └─────┘
327  | (some (a, s)) (some (b, t)) h := and.imp (H1 _ _) (H2 _ _) h
id                   └──┘            └─────┘  └┘       └┘
src                  └──┘             └─────┘
typ                  └──┘            └─────┘  └┘       └┘
328  | none          (some _)      h := false.elim h
id     └──┘           └──┘             └────────┘
src    └──┘           └──┘              └────────┘
typ    └──┘           └──┘             └────────┘
329  | (some (_, _)) none          h := false.elim h
id      └──┘        └──┘              └────────┘
src     └──┘        └──┘               └────────┘
typ     └──┘        └──┘              └────────┘
330  
331  theorem lift_rel_o.imp_right (R : α → β → Prop) {C D : wseq α → wseq β → Prop}
id                                                        └──┘    └──┘ 
src                                                         └──┘     └──┘
typ                                                       └──┘    └──┘ 
doc                                                         └──┘     └──┘
332    (H : ∀ s t, C s t → D s t) {o p} : lift_rel_o R C o p → lift_rel_o R D o p :=
id                                └────────┘       └────────┘    
src                                       └────────┘           └────────┘
typ                               └────────┘       └────────┘    
333  lift_rel_o.imp (λ _ _, id) H
id   └────────────┘       └┘  
src  └────────────┘         └┘
typ  └────────────┘       └┘  
334  
335  @[simp] def bisim_o (R : wseq α → wseq α → Prop) :
id                            └──┘    └──┘ 
src                           └──┘     └──┘
typ                           └──┘    └──┘ 
doc    └──┘                   └──┘     └──┘
336    option (α × wseq α) → option (α × wseq α) → Prop := lift_rel_o (=) R
id     └────┘    └──┘     └────┘    └──┘             └────────┘    
src    └────┘     └──┘      └────┘     └──┘              └────────┘ 
typ    └────┘    └──┘     └────┘    └──┘             └────────┘    
doc                └──┘                  └──┘
337  
338  theorem bisim_o.imp {R S : wseq α → wseq α → Prop} (H : ∀ s t, R s t → S s t) {o p} :
id                              └──┘    └──┘                           
src                             └──┘     └──┘
typ                             └──┘    └──┘                           
doc                             └──┘     └──┘
339    bisim_o R o p → bisim_o S o p :=
id     └─────┘      └─────┘   
src    └─────┘         └─────┘
typ    └─────┘      └─────┘   
340  lift_rel_o.imp_right _ H
id   └──────────────────┘   
src  └──────────────────┘
typ  └──────────────────┘   
341  
342  /-- Two weak sequences are `lift_rel R` related if they are either both empty,
343    or they are both nonempty and the heads are `R` related and the tails are
344    `lift_rel R` related. (This is a coinductive definition.) -/
345  def lift_rel (R : α → β → Prop) (s : wseq α) (t : wseq β) : Prop :=
id                                      └──┘        └──┘ 
src                                       └──┘         └──┘
typ                                     └──┘        └──┘ 
doc                                       └──┘         └──┘
346  ∃ C : wseq α → wseq β → Prop, C s t ∧
id        └──┘   └──┘            
src       └──┘     └──┘                
typ       └──┘   └──┘            
doc        └──┘     └──┘
347  ∀ {s t}, C s t → computation.lift_rel (lift_rel_o R C) (destruct s) (destruct t)
id               └──────────────────┘  └────────┘     └──────┘    └──────┘ 
src                   └──────────────────┘  └────────┘       └──────┘     └──────┘
typ              └──────────────────┘  └────────┘     └──────┘    └──────┘ 
doc                   └──────────────────┘                   └──────┘     └──────┘
348  
349  /-- If two sequences are equivalent, then they have the same values and
350    the same computational behavior (i.e. if one loops forever then so does
351    the other), although they may differ in the number of `think`s needed to
352    arrive at the answer. -/
353  def equiv : wseq α → wseq α → Prop := lift_rel (=)
id               └──┘    └──┘            └──────┘ 
src              └──┘     └──┘             └──────┘ 
typ              └──┘    └──┘            └──────┘ 
doc              └──┘     └──┘             └──────┘
354  
355  theorem lift_rel_destruct {R : α → β → Prop} {s : wseq α} {t : wseq β} :
id                                                   └──┘        └──┘ 
src                                                    └──┘         └──┘
typ                                                  └──┘        └──┘ 
doc                                                    └──┘         └──┘
356    lift_rel R s t →
id     └──────┘    
src    └──────┘
typ    └──────┘    
doc    └──────┘
357      computation.lift_rel (lift_rel_o R (lift_rel R)) (destruct s) (destruct t)
id       └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
src      └──────────────────┘  └────────┘    └──────┘      └──────┘     └──────┘
typ      └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
doc      └──────────────────┘                └──────┘      └──────┘     └──────┘
358  | ⟨R, h1, h2⟩ :=
359    by refine computation.lift_rel.imp _ _ _ (h2 h1);
id               └──────────────────────┘        └┘ └┘
src       └─────┘└──────────────────────┘└─────┘     
typ       └─────┘└──────────────────────┘└─────┘ └┘└┘
doc       └─────┘                        └─────┘     
txt       └─────┘                        └─────┘     
par       └─────┘                        └─────┘     
pid                                     └─────┘     
st       └───────────────────────────────────────────────
360       apply lift_rel_o.imp_right; exact λ s' t' h', ⟨R, h', @h2⟩
id              └──────────────────┘                            └┘
src       └────┘└──────────────────┘  └────┘ └─────────┘  └┘  └┘   └─
typ       └────┘└──────────────────┘  └────┘ └─────────┘ └┘  └┘ └┘└─
doc       └────┘                      └────┘ └─────────┘  └┘  └┘   └─
txt       └────┘                      └────┘ └─────────┘  └┘  └┘   └─
par       └────┘                      └────┘ └─────────┘  └┘  └┘   └─
pid                                        └─────────┘  └┘  └┘   
st   ────────────────────────────────────────────────────────────────
361  
src  
typ  
doc  
txt  
par  
pid  
st   
362  theorem lift_rel_destruct_iff {R : α → β → Prop} {s : wseq α} {t : wseq β} :
id                                                       └──┘        └──┘ 
src                                                        └──┘         └──┘
typ                                                      └──┘        └──┘ 
doc                                                        └──┘         └──┘
363    lift_rel R s t ↔
id     └──────┘    
src    └──────┘       
typ    └──────┘    
doc    └──────┘
364      computation.lift_rel (lift_rel_o R (lift_rel R)) (destruct s) (destruct t) :=
id       └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
src      └──────────────────┘  └────────┘    └──────┘      └──────┘     └──────┘
typ      └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
doc      └──────────────────┘                └──────┘      └──────┘     └──────┘
365  ⟨lift_rel_destruct, λ h, ⟨λ s t, lift_rel R s t ∨
id    └───────────────┘            └──────┘    
src   └───────────────┘               └──────┘       
typ   └───────────────┘            └──────┘    
doc                                   └──────┘
366    computation.lift_rel (lift_rel_o R (lift_rel R)) (destruct s) (destruct t),
id     └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
src    └──────────────────┘  └────────┘    └──────┘      └──────┘     └──────┘
typ    └──────────────────┘  └────────┘   └──────┘     └──────┘    └──────┘ 
doc    └──────────────────┘                └──────┘      └──────┘     └──────┘
367    or.inr h, λ s t h, begin
id     └────┘       
src    └────┘
typ    └────┘       
st                        └─────
368      have h : computation.lift_rel (lift_rel_o R (lift_rel R)) (destruct s) (destruct t),
id                └──────────────────┘  └────────┘    └──────┘                 └──────┘ 
src      └───────┘└──────────────────┘ └────────┘  └──────┘ └─┘          └┘ └──────┘ 
typ      └───────┘└──────────────────┘ └────────┘  └──────┘└─┘         └┘ └──────┘
doc      └───────┘└──────────────────┘             └──────┘ └─┘          └┘ └──────┘ 
txt      └───────┘                                          └─┘          └┘          
par      └───────┘                                          └─┘          └┘          
pid      └────┘└─┘                                          └─┘          └┘          
st   ──────────────────────────────────────────────────────────────────────────────────────┘└─
369      { cases h with h h, exact lift_rel_destruct h, assumption },
id                                └───────────────┘ 
src        └────┘ └───────┘  └────┘└───────────────┘   └─────────┘
typ        └────┘└───────┘  └────┘└───────────────┘  └─────────┘
doc        └────┘ └───────┘  └────┘                    └─────────┘
txt        └────┘ └───────┘  └────┘                    └─────────┘
par        └────┘ └───────┘  └────┘                    └─────────┘
pid              └───────┘                                     
st   ─────┘└──────────────┘└─────────────────────────┘└───────────┘└┘
370      apply computation.lift_rel.imp _ _ _ h,
id             └──────────────────────┘       
src      └────┘└──────────────────────┘└─────┘
typ      └────┘└──────────────────────┘└─────┘
doc      └────┘                        └─────┘
txt      └────┘                        └─────┘
par      └────┘                        └─────┘
pid                                   └─────┘
st   ─────────────────────────────────────────┘└─
371      intros a b, apply lift_rel_o.imp_right,
id                         └──────────────────┘
src      └────────┘  └────┘└──────────────────┘
typ      └────────┘  └────┘└──────────────────┘
doc      └────────┘  └────┘
txt      └────────┘  └────┘
par      └────────┘  └────┘
pid            └──┘       
st   ─────────────┘└──────────────────────────┘└─
372      intros s t, apply or.inl
id                         └────┘
src      └────────┘  └────┘└────┘
typ      └────────┘  └────┘└────┘
doc      └────────┘  └────┘      
txt      └────────┘  └────┘      
par      └────────┘  └────┘      
pid            └──┘             
st   ─────────────┘└──────────────
373    end⟩⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
374  
375  infix ~ := equiv
id              └───┘
src             └───┘
typ             └───┘
doc             └───┘
376  
377  theorem destruct_congr {s t : wseq α} :
id                                 └──┘ 
src                                └──┘
typ                                └──┘ 
doc                                └──┘
378    s ~ t → computation.lift_rel (bisim_o (~)) (destruct s) (destruct t) :=
id          └──────────────────┘  └─────┘      └──────┘    └──────┘ 
src           └──────────────────┘  └─────┘      └──────┘     └──────┘
typ         └──────────────────┘  └─────┘      └──────┘    └──────┘ 
doc           └──────────────────┘               └──────┘     └──────┘
379  lift_rel_destruct
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
380  
381  theorem destruct_congr_iff {s t : wseq α} :
id                                     └──┘ 
src                                    └──┘
typ                                    └──┘ 
doc                                    └──┘
382    s ~ t ↔ computation.lift_rel (bisim_o (~)) (destruct s) (destruct t) :=
id         └──────────────────┘  └─────┘      └──────┘    └──────┘ 
src          └──────────────────┘  └─────┘      └──────┘     └──────┘
typ        └──────────────────┘  └─────┘      └──────┘    └──────┘ 
doc           └──────────────────┘               └──────┘     └──────┘
383  lift_rel_destruct_iff
id   └───────────────────┘
src  └───────────────────┘
typ  └───────────────────┘
384  
385  theorem lift_rel.refl (R : α → α → Prop) (H : reflexive R) : reflexive (lift_rel R) :=
id                                               └───────┘     └───────┘  └──────┘ 
src                                                └───────┘      └───────┘  └──────┘
typ                                              └───────┘     └───────┘  └──────┘ 
doc                                                                          └──────┘
386  λ s, begin
id     
typ    
st        └─────
387    refine ⟨(=), rfl, λ s t (h : s = t), _⟩,
id                 └─┘               
src    └─────┘ └──┘└─┘└┘ └────────┘   └───┘
typ    └─────┘ └──┘└─┘└┘ └────────┘  └───┘
doc    └─────┘  └──┘   └┘ └────────┘   └───┘
txt    └─────┘  └──┘   └┘ └────────┘   └───┘
par    └─────┘  └──┘   └┘ └────────┘   └───┘
pid            └──┘   └┘ └────────┘   └───┘
st   ────────────────────────────────────────┘└─
388    rw ←h, apply computation.lift_rel.refl,
id                 └───────────────────────┘
src    └──┘   └────┘└───────────────────────┘
typ    └──┘  └────┘└───────────────────────┘
doc    └──┘   └────┘
txt    └──┘   └────┘
par    └──┘   └────┘
pid      └┘        
st   ──────┘└───────────────────────────────┘└─
389    intro a, cases a with a, simp, cases a; simp, apply H
id                                         
src    └─────┘  └────┘ └─────┘  └──┘  └────┘   └──┘  └────┘ 
typ    └─────┘  └────┘└─────┘  └──┘  └────┘  └──┘  └────┘ 
doc    └─────┘  └────┘ └─────┘  └──┘  └────┘   └──┘  └────┘ 
txt    └─────┘  └────┘ └─────┘  └──┘  └────┘   └──┘  └────┘ 
par    └─────┘  └────┘ └─────┘  └──┘  └────┘   └──┘  └────┘ 
pid         └┘        └─────┘                            
st   ────────┘└──────────────┘└────┘└─────────────┘└────────┘
390  end
st   └─┘
391  
392  theorem lift_rel_o.swap (R : α → β → Prop) (C) :
id                                   
typ                                  
393    function.swap (lift_rel_o R C) = lift_rel_o (function.swap R) (function.swap C) :=
id     └───────────┘  └────────┘     └────────┘  └───────────┘    └───────────┘ 
src    └───────────┘  └────────┘       └────────┘  └───────────┘     └───────────┘
typ    └───────────┘  └────────┘     └────────┘  └───────────┘    └───────────┘ 
394  by funext x y; cases x with x; [skip, cases x]; { cases y with y; [skip, cases y]; refl }
id                                                                             
src     └────────┘  └────┘ └─────┘  └──┘  └────┘      └────┘ └─────┘  └──┘  └────┘    └───┘
typ     └────────┘  └────┘└─────┘  └──┘  └────┘     └────┘└─────┘  └──┘  └────┘   └───┘
doc     └────────┘  └────┘ └─────┘   └──┘  └────┘      └────┘ └─────┘   └──┘  └────┘    └───┘
txt     └────────┘  └────┘ └─────┘   └──┘  └────┘      └────┘ └─────┘   └──┘  └────┘    └───┘
par     └────────┘  └────┘ └─────┘   └──┘  └────┘      └────┘ └─────┘   └──┘  └────┘    └───┘
pid           └──┘        └─────┘                          └─────┘                      
st     └────────────────────────────────────────────┘└──────────────────────────────────────┘└┘
395  
396  theorem lift_rel.swap_lem {R : α → β → Prop} {s1 s2} (h : lift_rel R s1 s2) :
id                                                           └──────┘  └┘ └┘
src                                                            └──────┘
typ                                                          └──────┘  └┘ └┘
doc                                                            └──────┘
397    lift_rel (function.swap R) s2 s1 :=
id     └──────┘  └───────────┘   └┘ └┘
src    └──────┘  └───────────┘
typ    └──────┘  └───────────┘   └┘ └┘
doc    └──────┘
398  begin
st   └─────
399    refine ⟨function.swap (lift_rel R), h, λ s t (h : lift_rel R t s), _⟩,
id             └───────────┘                            └──────┘ 
src    └─────┘ └───────────┘          └─┘ └┘ └────────┘└──────┘   └───┘
typ    └─────┘ └───────────┘          └─┘└┘ └────────┘└──────┘  └───┘
doc    └─────┘                        └─┘ └┘ └────────┘└──────┘   └───┘
txt    └─────┘                        └─┘ └┘ └────────┘           └───┘
par    └─────┘                        └─┘ └┘ └────────┘           └───┘
pid                                  └─┘ └┘ └────────┘           └───┘
st   ──────────────────────────────────────────────────────────────────────┘└─
400    rw [←lift_rel_o.swap, computation.lift_rel.swap],
id          └─────────────┘  └───────────────────────┘
src    └───┘└─────────────┘└┘└───────────────────────┘
typ    └───┘└─────────────┘└┘└───────────────────────┘
doc    └───┘               └┘                         
txt    └───┘               └┘                         
par    └───┘               └┘                         
pid      └─┘               └┘                         
st   ─────────────────────┘└─────────────────────────┘└──
401    apply lift_rel_destruct h
id           └───────────────┘ 
src    └────┘└───────────────┘ 
typ    └────┘└───────────────┘
doc    └────┘                  
txt    └────┘                  
par    └────┘                  
pid                           
st   ───────────────────────────┘
402  end
st   └─┘
403  
404  theorem lift_rel.swap (R : α → β → Prop) :
id                                 
typ                                
405    function.swap (lift_rel R) = lift_rel (function.swap R) :=
id     └───────────┘  └──────┘    └──────┘  └───────────┘ 
src    └───────────┘  └──────┘     └──────┘  └───────────┘
typ    └───────────┘  └──────┘    └──────┘  └───────────┘ 
doc                   └──────┘      └──────┘
406  funext $ λ x, funext $ λ y, propext ⟨lift_rel.swap_lem, lift_rel.swap_lem⟩
id   └────┘       └────┘       └─────┘  └───────────────┘  └───────────────┘
src  └────┘        └────┘        └─────┘  └───────────────┘  └───────────────┘
typ  └────┘       └────┘       └─────┘  └───────────────┘  └───────────────┘
407  
408  theorem lift_rel.symm (R : α → α → Prop) (H : symmetric R) : symmetric (lift_rel R) :=
id                                               └───────┘     └───────┘  └──────┘ 
src                                                └───────┘      └───────┘  └──────┘
typ                                              └───────┘     └───────┘  └──────┘ 
doc                                                                          └──────┘
409  λ s1 s2 (h : function.swap (lift_rel R) s2 s1),
id     └┘ └┘      └───────────┘  └──────┘   └┘ └┘
src               └───────────┘  └──────┘
typ    └┘ └┘      └───────────┘  └──────┘   └┘ └┘
doc                              └──────┘
410  by rwa [lift_rel.swap, show function.swap R = R, from
id           └───────────┘       └───────────┘    
src     └───┘└───────────┘└┘    └───────────┘  └──────
typ     └───┘└───────────┘└┘    └───────────┘ └──────
doc     └───┘             └┘                    └──────
txt     └───┘             └┘                    └──────
par     └───┘             └┘                    └──────
pid        └┘             └┘                    └──────
st     └─────────────────┘└────────────────────────────────
411          funext $ λ a, funext $ λ b, propext $ by constructor; apply H] at h
id                         └────┘        └─────┘
src  ───────┘        └──┘└────┘  └──┘└─────┘   └─────────┘└┘└────┘ └──────
typ  ───────┘        └──┘└────┘  └──┘└─────┘   └─────────┘└┘└────┘ └──────
doc  ───────┘        └──┘        └──┘          └─────────┘└┘└────┘ └──────
txt  ───────┘        └──┘        └──┘          └─────────┘└┘└────┘ └──────
par  ───────┘        └──┘        └──┘          └─────────┘└┘└────┘ └──────
pid  ───────┘        └──┘        └──┘          └──────────────────┘ └───┘
st   ───────────────────────────────────────────────┘└───────────────────┘└─────
412  
src  
typ  
doc  
txt  
par  
pid  
st   
413  theorem lift_rel.trans (R : α → α → Prop) (H : transitive R) : transitive (lift_rel R) :=
id                                                └────────┘     └────────┘  └──────┘ 
src                                                 └────────┘      └────────┘  └──────┘
typ                                               └────────┘     └────────┘  └──────┘ 
doc                                                                             └──────┘
414  λ s t u h1 h2, begin
id        └┘ └┘
typ       └┘ └┘
st                  └─────
415    refine ⟨λ s u, ∃ t, lift_rel R s t ∧ lift_rel R t u, ⟨t, h1, h2⟩, λ s u h, _⟩,
id                                       └──────┘          └┘  └┘
src    └─────┘  └────┘└┘           └──────┘   └┘  └┘  └┘  └─┘ └────────┘
typ    └─────┘  └────┘└┘           └──────┘  └┘ └┘└┘└┘└┘└─┘ └────────┘
doc    └─────┘  └────┘ └┘             └──────┘   └┘  └┘  └┘  └─┘ └────────┘
txt    └─────┘  └────┘ └┘                        └┘  └┘  └┘  └─┘ └────────┘
par    └─────┘  └────┘ └┘                        └┘  └┘  └┘  └─┘ └────────┘
pid            └────┘ └┘                        └┘  └┘  └┘  └─┘ └────────┘
st   ──────────────────────────────────────────────────────────────────────────────┘└─
416    rcases h with ⟨t, h1, h2⟩,
id            
src    └─────┘ └───────────────┘
typ    └─────┘└───────────────┘
doc    └─────┘ └───────────────┘
txt    └─────┘ └───────────────┘
par    └─────┘ └───────────────┘
pid           └───────────────┘
st   ──────────────────────────┘└─
417    have h1 := lift_rel_destruct h1,
id                └───────────────┘ └┘
src    └─────────┘└───────────────┘
typ    └─────────┘└───────────────┘└┘
doc    └─────────┘                 
txt    └─────────┘                 
par    └─────────┘                 
pid    └─────┘└─┘                 
st   ────────────────────────────────┘└─
418    have h2 := lift_rel_destruct h2,
id                └───────────────┘ └┘
src    └─────────┘└───────────────┘
typ    └─────────┘└───────────────┘└┘
doc    └─────────┘                 
txt    └─────────┘                 
par    └─────────┘                 
pid    └─────┘└─┘                 
st   ────────────────────────────────┘└─
419    refine computation.lift_rel_def.2
id            └──────────────────────┘
src    └─────┘└──────────────────────┘└──
typ    └─────┘└──────────────────────┘└──
doc    └─────┘                        └──
txt    └─────┘                        └──
par    └─────┘                        └──
pid                                  └──
st   ────────────────────────────────────
420      ⟨(computation.terminates_of_lift_rel h1).trans
id                                            └┘
src  ───┘                                      └───────
typ  ───┘                                    └┘└───────
doc  ───┘                                      └───────
txt  ───┘                                      └───────
par  ───┘                                      └───────
pid  ───┘                                      └───────
st   ───────────────────────────────────────────────────
421       (computation.terminates_of_lift_rel h2), λ a c ha hc, _⟩,
id         └────────────────────────────────┘ └┘
src  ────┘ └────────────────────────────────┘  └─┘ └────────────┘
typ  ────┘ └────────────────────────────────┘└┘└─┘ └────────────┘
doc  ────┘                                     └─┘ └────────────┘
txt  ────┘                                     └─┘ └────────────┘
par  ────┘                                     └─┘ └────────────┘
pid  ────┘                                     └─┘ └────────────┘
st   ────────────────────────────────────────────────────────────┘└─
422    rcases h1.left ha with ⟨b, hb, t1⟩,
id            └─────┘ └┘
src    └─────┘└─────┘  └───────────────┘
typ    └─────┘└─────┘└┘└───────────────┘
doc    └─────┘         └───────────────┘
txt    └─────┘         └───────────────┘
par    └─────┘         └───────────────┘
pid                   └───────────────┘
st   ───────────────────────────────────┘└─
423    have t2 := computation.rel_of_lift_rel h2 hb hc,
id                └─────────────────────────┘ └┘ └┘ └┘
src    └─────────┘└─────────────────────────┘    
typ    └─────────┘└─────────────────────────┘└┘└┘└┘
doc    └─────────┘                               
txt    └─────────┘                               
par    └─────────┘                               
pid    └─────┘└─┘                               
st   ────────────────────────────────────────────────┘└─
424    cases a with a; cases c with c,
id                          
src    └────┘ └─────┘  └────┘ └─────┘
typ    └────┘└─────┘  └────┘└─────┘
doc    └────┘ └─────┘  └────┘ └─────┘
txt    └────┘ └─────┘  └────┘ └─────┘
par    └────┘ └─────┘  └────┘ └─────┘
pid          └─────┘        └─────┘
st   ───────────────────────────────┘└─
425    { trivial },
src      └──────┘
typ      └──────┘
doc      └──────┘
txt      └──────┘
par      └──────┘
pid             
st   ───┘└──────┘└┘
426    { cases b, {cases t2}, {cases t1} },
id                      └┘          └┘
src      └────┘    └────┘      └────┘
typ      └────┘   └────┘└┘    └────┘└┘
doc      └────┘    └────┘      └────┘
txt      └────┘    └────┘      └────┘
par      └────┘    └────┘      └────┘
pid                               
st   ───┘└─────┘└─────────┘└┘└────────┘└──┘
427    { cases a, cases b with b, {cases t1}, {cases b, cases t2} },
id                                     └┘                  └┘
src      └────┘   └────┘ └─────┘   └────┘      └────┘   └────┘
typ      └────┘  └────┘└─────┘   └────┘└┘    └────┘  └────┘└┘
doc      └────┘   └────┘ └─────┘   └────┘      └────┘   └────┘
txt      └────┘   └────┘ └─────┘   └────┘      └────┘   └────┘
par      └────┘   └────┘ └─────┘   └────┘      └────┘   └────┘
pid                    └─────┘                           
st   ───┘└─────┘└──────────────┘└─────────┘└┘└───────┘└────────┘└──┘
428    { cases a with a s, cases b with b, {cases t1},
id                                              └┘
src      └────┘ └───────┘  └────┘ └─────┘   └────┘
typ      └────┘└───────┘  └────┘└─────┘   └────┘└┘
doc      └────┘ └───────┘  └────┘ └─────┘   └────┘
txt      └────┘ └───────┘  └────┘ └─────┘   └────┘
par      └────┘ └───────┘  └────┘ └─────┘   └────┘
pid            └───────┘        └─────┘        
st   ───────────────────┘└──────────────┘└─────────┘└┘
429      cases b with b t, cases c with c u,
id                              
src      └────┘ └───────┘  └────┘ └───────┘
typ      └────┘└───────┘  └────┘└───────┘
doc      └────┘ └───────┘  └────┘ └───────┘
txt      └────┘ └───────┘  └────┘ └───────┘
par      └────┘ └───────┘  └────┘ └───────┘
pid            └───────┘        └───────┘
st   ───────────────────┘└────────────────┘└─
430      cases t1 with ab st, cases t2 with bc tu,
id             └┘                   └┘
src      └────┘  └─────────┘  └────┘  └─────────┘
typ      └────┘└┘└─────────┘  └────┘└┘└─────────┘
doc      └────┘  └─────────┘  └────┘  └─────────┘
txt      └────┘  └─────────┘  └────┘  └─────────┘
par      └────┘  └─────────┘  └────┘  └─────────┘
pid             └─────────┘         └─────────┘
st   ──────────────────────┘└───────────────────┘└─
431      exact ⟨H ab bc, t, st, tu⟩ }
id               └┘ └┘    └┘  └┘
src      └────┘      └┘ └┘  └┘  └┘
typ      └────┘ └┘└┘└┘└┘└┘└┘└┘└┘
doc      └────┘      └┘ └┘  └┘  └┘
txt      └────┘      └┘ └┘  └┘  └┘
par      └────┘      └┘ └┘  └┘  └┘
pid                 └┘ └┘  └┘  
st   ──────────────────────────────┘└─
432  end
st   ──┘
433  
434  theorem lift_rel.equiv (R : α → α → Prop) : equivalence R → equivalence (lift_rel R)
id                                             └─────────┘   └─────────┘  └──────┘ 
src                                              └─────────┘     └─────────┘  └──────┘
typ                                            └─────────┘   └─────────┘  └──────┘ 
doc                                                                           └──────┘
435  | ⟨refl, symm, trans⟩ :=
id      └──┘  └──┘  └───┘
src     └──┘  └──┘  └───┘
typ     └──┘  └──┘  └───┘
436    ⟨lift_rel.refl R refl, lift_rel.symm R symm, lift_rel.trans R trans⟩
id      └───────────┘        └───────────┘        └────────────┘ 
src     └───────────┘         └───────────┘         └────────────┘
typ     └───────────┘        └───────────┘        └────────────┘ 
437  
438  @[refl] theorem equiv.refl : ∀ (s : wseq α), s ~ s :=
id                                       └──┘      
src    └──┘                              └──┘       
typ                                      └──┘      
doc    └──┘                              └──┘       
439  lift_rel.refl (=) eq.refl
id   └───────────┘    └─────┘
src  └───────────┘    └─────┘
typ  └───────────┘    └─────┘
440  
441  @[symm] theorem equiv.symm : ∀ {s t : wseq α}, s ~ t → t ~ s :=
id                                         └──┘           
src    └──┘                                └──┘              
typ                                        └──┘           
doc    └──┘                                └──┘              
442  lift_rel.symm (=) (@eq.symm _)
id   └───────────┘      └─────┘
src  └───────────┘      └─────┘
typ  └───────────┘      └─────┘
443  
444  @[trans] theorem equiv.trans : ∀ {s t u : wseq α}, s ~ t → t ~ u → s ~ u :=
id                                             └──┘                
src    └───┘                                   └──┘                     
typ                                            └──┘                
doc    └───┘                                   └──┘                     
445  lift_rel.trans (=) (@eq.trans _)
id   └────────────┘      └──────┘
src  └────────────┘      └──────┘
typ  └────────────┘      └──────┘
446  
447  theorem equiv.equivalence : equivalence (@equiv α) :=
id                               └─────────┘   └───┘ 
src                              └─────────┘   └───┘
typ                              └─────────┘   └───┘ 
doc                                            └───┘
448  ⟨@equiv.refl _, @equiv.symm _, @equiv.trans _⟩
id     └────────┘     └────────┘     └─────────┘
src    └────────┘     └────────┘     └─────────┘
typ    └────────┘     └────────┘     └─────────┘
449  
450  open computation
451  local notation `return` := computation.return
id                              └────────────────┘
src                             └────────────────┘
typ                             └────────────────┘
doc                             └────────────────┘
452  
453  @[simp] theorem destruct_nil : destruct (nil : wseq α) = return none :=
id                                  └──────┘  └─┘   └──┘    └────┘ └──┘
src                                 └──────┘  └─┘   └──┘     └────┘ └──┘
typ                                 └──────┘  └─┘   └──┘    └────┘ └──┘
doc    └──┘                         └──────┘  └─┘   └──┘      └────┘
454  computation.destruct_eq_ret rfl
id   └─────────────────────────┘ └─┘
src  └─────────────────────────┘ └─┘
typ  └─────────────────────────┘ └─┘
455  
456  @[simp] theorem destruct_cons (a : α) (s) : destruct (cons a s) = return (some (a, s)) :=
id                                              └──────┘  └──┘     └────┘  └──┘   
src                                              └──────┘  └──┘       └────┘  └──┘ 
typ                                             └──────┘  └──┘     └────┘  └──┘   
doc    └──┘                                      └──────┘  └──┘        └────┘
457  computation.destruct_eq_ret $ by simp [destruct, cons, computation.rmap]
id   └─────────────────────────┘            └──────┘  └──┘  └──────────────┘
src  └─────────────────────────┘      └────┘└──────┘└┘└──┘└┘└──────────────┘└─
typ  └─────────────────────────┘      └────┘└──────┘└┘└──┘└┘└──────────────┘└─
doc                                   └────┘└──────┘└┘└──┘└┘└──────────────┘└─
txt                                   └────┘        └┘    └┘                └─
par                                   └────┘        └┘    └┘                └─
pid                                               └┘    └┘                
st                                   └────────────────────────────────────────
458  
src  
typ  
doc  
txt  
par  
pid  
st   
459  @[simp] theorem destruct_think (s : wseq α) : destruct (think s) = (destruct s).think :=
id                                       └──┘     └──────┘  └───┘     └──────┘  └───┘
src                                      └──┘      └──────┘  └───┘      └──────┘   └───┘
typ                                      └──┘     └──────┘  └───┘     └──────┘  └───┘
doc    └──┘                              └──┘      └──────┘  └───┘       └──────┘   └───┘
460  computation.destruct_eq_think $ by simp [destruct, think, computation.rmap]
id   └───────────────────────────┘            └──────┘  └───┘  └──────────────┘
src  └───────────────────────────┘      └────┘└──────┘└┘└───┘└┘└──────────────┘└─
typ  └───────────────────────────┘      └────┘└──────┘└┘└───┘└┘└──────────────┘└─
doc                                     └────┘└──────┘└┘└───┘└┘└──────────────┘└─
txt                                     └────┘        └┘     └┘                └─
par                                     └────┘        └┘     └┘                └─
pid                                                 └┘     └┘                
st                                     └─────────────────────────────────────────
461  
src  
typ  
doc  
txt  
par  
pid  
st   
462  @[simp] theorem seq_destruct_nil : seq.destruct (nil : wseq α) = none :=
id                                      └──────────┘  └─┘   └──┘    └──┘
src                                     └──────────┘  └─┘   └──┘     └──┘
typ                                     └──────────┘  └─┘   └──┘    └──┘
doc    └──┘                             └──────────┘  └─┘   └──┘
463  seq.destruct_nil
id   └──────────────┘
src  └──────────────┘
typ  └──────────────┘
464  
465  @[simp] theorem seq_destruct_cons (a : α) (s) : seq.destruct (cons a s) = some (some a, s) :=
id                                                  └──────────┘  └──┘     └──┘ └──┘   
src                                                  └──────────┘  └──┘       └──┘ └──┘
typ                                                 └──────────┘  └──┘     └──┘ └──┘   
doc    └──┘                                          └──────────┘  └──┘
466  seq.destruct_cons _ _
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
467  
468  @[simp] theorem seq_destruct_think (s : wseq α) : seq.destruct (think s) = some (none, s) :=
id                                           └──┘     └──────────┘  └───┘    └──┘ └──┘  
src                                          └──┘      └──────────┘  └───┘     └──┘ └──┘
typ                                          └──┘     └──────────┘  └───┘    └──┘ └──┘  
doc    └──┘                                  └──┘      └──────────┘  └───┘
469  seq.destruct_cons _ _
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
470  
471  @[simp] theorem head_nil : head (nil : wseq α) = return none := by simp [head]; refl
id                              └──┘  └─┘   └──┘    └────┘ └──┘             └──┘
src                             └──┘  └─┘   └──┘     └────┘ └──┘       └────┘└──┘  └───┘
typ                             └──┘  └─┘   └──┘    └────┘ └──┘       └────┘└──┘  └───┘
doc    └──┘                     └──┘  └─┘   └──┘      └────┘            └────┘└──┘  └───┘
txt                                                                     └────┘      └───┘
par                                                                     └────┘      └───┘
pid                                                                                   
st                                                                     └─────────────────┘
472  @[simp] theorem head_cons (a : α) (s) : head (cons a s) = return (some a) := by simp [head]; refl
id                                          └──┘  └──┘     └────┘  └──┘               └──┘
src                                          └──┘  └──┘       └────┘  └──┘          └────┘└──┘  └───┘
typ                                         └──┘  └──┘     └────┘  └──┘         └────┘└──┘  └───┘
doc    └──┘                                  └──┘  └──┘        └────┘                └────┘└──┘  └───┘
txt                                                                                  └────┘      └───┘
par                                                                                  └────┘      └───┘
pid                                                                                                
st                                                                                  └─────────────────┘
473  @[simp] theorem head_think (s : wseq α) : head (think s) = (head s).think := by simp [head]; refl
id                                   └──┘     └──┘  └───┘     └──┘  └───┘              └──┘
src                                  └──┘      └──┘  └───┘      └──┘   └───┘        └────┘└──┘  └────
typ                                  └──┘     └──┘  └───┘     └──┘  └───┘        └────┘└──┘  └────
doc    └──┘                          └──┘      └──┘  └───┘       └──┘   └───┘        └────┘└──┘  └────
txt                                                                                  └────┘      └────
par                                                                                  └────┘      └────
pid                                                                                                
st                                                                                  └──────────────────
474  
src  
typ  
doc  
txt  
par  
pid  
st   
475  @[simp] theorem flatten_ret (s : wseq α) : flatten (return s) = s :=
id                                    └──┘     └─────┘  └────┘    
src                                   └──┘      └─────┘  └────┘    
typ                                   └──┘     └─────┘  └────┘    
doc    └──┘                           └──┘      └─────┘  └────┘
476  begin
st   └─────
477    refine seq.eq_of_bisim (λs1 s2, flatten (return s2) = s1) _ rfl,
id            └─────────────┘          └─────┘  └────┘            └─┘
src    └─────┘└─────────────┘  └─────┘└─────┘ └────┘  └┘  └──┘└─┘
typ    └─────┘└─────────────┘  └─────┘└─────┘ └────┘  └┘  └──┘└─┘
doc    └─────┘                 └─────┘└─────┘ └────┘  └┘   └──┘
txt    └─────┘                 └─────┘                └┘   └──┘
par    └─────┘                 └─────┘                └┘   └──┘
pid                           └─────┘                └┘   └──┘
st   ────────────────────────────────────────────────────────────────┘└─
478    intros s' s h, rw ←h, simp [flatten],
id                                └─────┘
src    └───────────┘  └──┘   └────┘└─────┘
typ    └───────────┘  └──┘  └────┘└─────┘
doc    └───────────┘  └──┘   └────┘└─────┘
txt    └───────────┘  └──┘   └────┘       
par    └───────────┘  └──┘   └────┘       
pid          └─────┘    └┘              
st   ──────────────┘└─────┘└──────────────┘└─
479    cases seq.destruct s, { simp },
id           └──────────┘ 
src    └────┘└──────────┘     └───┘
typ    └────┘└──────────┘    └───┘
doc    └────┘└──────────┘     └───┘
txt    └────┘                 └───┘
par    └────┘                 └───┘
pid                              
st   ─────────────────────┘└──┘└───┘└┘
480    { cases val with o s', simp }
id             └─┘
src      └────┘   └────────┘  └───┘
typ      └────┘└─┘└────────┘  └───┘
doc      └────┘   └────────┘  └───┘
txt      └────┘   └────────┘  └───┘
par      └────┘   └────────┘  └───┘
pid              └────────┘      
st   ──────────────────────┘└─────┘└─
481  end
st   ──┘
482  
483  @[simp] theorem flatten_think (c : computation (wseq α)) : flatten c.think = think (flatten c) :=
id                                      └─────────┘  └──┘      └─────┘ └────┘  └───┘  └─────┘ 
src                                     └─────────┘  └──┘       └─────┘  └────┘  └───┘  └─────┘
typ                                     └─────────┘  └──┘      └─────┘ └────┘  └───┘  └─────┘ 
doc    └──┘                             └─────────┘  └──┘       └─────┘  └────┘   └───┘  └─────┘
484  seq.destruct_eq_cons $ by simp [flatten, think]
id   └──────────────────┘            └─────┘  └───┘
src  └──────────────────┘      └────┘└─────┘└┘└───┘└─
typ  └──────────────────┘      └────┘└─────┘└┘└───┘└─
doc                            └────┘└─────┘└┘└───┘└─
txt                            └────┘       └┘     └─
par                            └────┘       └┘     └─
pid                                       └┘     
st                            └──────────────────────
485  
src  
typ  
doc  
txt  
par  
pid  
st   
486  @[simp] theorem destruct_flatten (c : computation (wseq α)) : destruct (flatten c) = c >>= destruct :=
id                                         └─────────┘  └──┘      └──────┘  └─────┘     └─┘ └──────┘
src                                        └─────────┘  └──┘       └──────┘  └─────┘       └─┘ └──────┘
typ                                        └─────────┘  └──┘      └──────┘  └─────┘     └─┘ └──────┘
doc    └──┘                                └─────────┘  └──┘       └──────┘  └─────┘            └──────┘
487  begin
st   └─────
488    refine computation.eq_of_bisim (λc1 c2, c1 = c2 ∨
id            └─────────────────────┘                 
src    └─────┘└─────────────────────┘  └─────┘    
typ    └─────┘└─────────────────────┘  └─────┘    
doc    └─────┘                         └─────┘      
txt    └─────┘                         └─────┘      
par    └─────┘                         └─────┘      
pid                                   └─────┘      
st   ────────────────────────────────────────────────────
489      ∃ c, c1 = destruct (flatten c) ∧ c2 = computation.bind c destruct) _ (or.inr ⟨c, rfl, rfl⟩),
id                         └─────┘          └──────────────┘   └──────┘     └────┘         └─┘
src  ───┘└┘            └─────┘ └┘   └──────────────┘ └──────┘└──┘ └────┘  └┘   └┘└─┘└┘
typ  ───┘└┘            └─────┘ └┘   └──────────────┘ └──────┘└──┘ └────┘ └┘   └┘└─┘└┘
doc  ───┘ └┘             └─────┘ └┘    └──────────────┘ └──────┘└──┘         └┘   └┘   └┘
txt  ───┘ └┘                     └┘                             └──┘         └┘   └┘   └┘
par  ───┘ └┘                     └┘                             └──┘         └┘   └┘   └┘
pid  ───┘ └┘                     └┘                             └──┘         └┘   └┘   └┘
st   ──────────────────────────────────────────────────────────────────────────────────────────────┘└─
490    intros c1 c2 h, exact match c1, c2, h with
id                                 └┘  └┘  
src    └────────────┘  └────┘       └┘  └┘ └─────
typ    └────────────┘  └────┘     └┘└┘└┘└┘└─────
doc    └────────────┘  └────┘       └┘  └┘ └─────
txt    └────────────┘  └────┘       └┘  └┘ └─────
par    └────────────┘  └────┘       └┘  └┘ └─────
pid          └──────┘              └┘  └┘ └─────
st   ───────────────┘└────────────────────────────
491    | _, _, (or.inl $ eq.refl c) := by cases c.destruct; simp
id              └────┘   └─────┘                └────────┘
src  ─────────┘ └────┘ └─────┘ └───┘  └────┘└────────┘└┘└────
typ  ─────────┘ └────┘ └─────┘ └───┘  └────┘└────────┘└┘└────
doc  ─────────┘                └───┘  └────┘└────────┘└┘└────
txt  ─────────┘                └───┘  └────┘          └┘└────
par  ─────────┘                └───┘  └────┘          └┘└────
pid  ─────────┘                └───┘  └─────┘          └──────
st   ───────────────────────────────────┘└───────────────────────
492    | _, _, (or.inr ⟨c, rfl, rfl⟩) := begin
src  ─┘└──────┘         └┘   └┘   └────┘     
typ  ─┘└──────┘         └┘   └┘   └────┘     
doc  ─┘└──────┘         └┘   └┘   └────┘     
txt  ─┘└──────┘         └┘   └┘   └────┘     
par  ─┘└──────┘         └┘   └┘   └────┘     
pid  ─────────┘         └┘   └┘   └────┘     
st   ─┘└────────────────────────────────┘└─────
493      apply c.cases_on (λa, _) (λc', _); repeat {simp},
id             └────────┘
src  ───┘└────┘└────────┘  └────┘  └────┘└┘└──────┘└──┘└─
typ  ─────────┘└────────┘  └────┘  └──────┘└──────┘└──┘└─
doc  ───┘└────┘            └────┘  └────┘└┘└──────┘└──┘└─
txt  ───┘└────┘            └────┘  └────┘└┘└──────┘└──┘└─
par  ─────────┘            └────┘  └──────┘└──────┘└──┘└─
pid  ─────────┘            └────┘  └──────────────────────
st   ──────────────────────────────────────────────┘└───┘└─
494      { cases (destruct a).destruct; simp },
id                └──────┘ 
src  ─────┘└────┘ └──────┘ └────────┘└┘└───┘└──
typ  ─────┘└────┘ └──────┘└────────┘└┘└───┘└──
doc  ─────┘└────┘ └──────┘ └────────┘└┘└───┘└──
txt  ─────┘└────┘          └────────┘└┘└───┘└──
par  ─────┘└────┘          └────────┘└┘└───┘└──
pid  ───────────┘          └───────────────────
st   ────┘└─────────────────────────────────┘└─
495      { exact or.inr ⟨c', rfl, rfl⟩ }
id               └────┘  └┘       └─┘
src  ───────────┘└────┘   └┘   └┘└─┘└───
typ  ───────────┘└────┘ └┘└┘   └┘└─┘└───
doc  ───────────┘         └┘   └┘   └───
txt  ───────────┘         └┘   └┘   └───
par  ───────────┘         └┘   └┘   └───
pid  ───────────┘         └┘   └┘   └───
st   ─────────────────────────────────┘└─
496    end end
src  ─────────┘
typ  ─────────┘
doc  ─────────┘
txt  ─────────┘
par  ─────────┘
pid  ────────┘
st   ────┘└───┘
497  end
st   └─┘
498  
499  theorem head_terminates_iff (s : wseq α) : terminates (head s) ↔ terminates (destruct s) :=
id                                    └──┘     └────────┘  └──┘    └────────┘  └──────┘ 
src                                   └──┘      └────────┘  └──┘     └────────┘  └──────┘
typ                                   └──┘     └────────┘  └──┘    └────────┘  └──────┘ 
doc                                   └──┘      └────────┘  └──┘      └────────┘  └──────┘
500  terminates_map_iff _ (destruct s)
id   └────────────────┘    └──────┘ 
src  └────────────────┘    └──────┘
typ  └────────────────┘    └──────┘ 
doc                        └──────┘
501  
502  @[simp] theorem tail_nil : tail (nil : wseq α) = nil := by simp [tail]
id                              └──┘  └─┘   └──┘    └─┘             └──┘
src                             └──┘  └─┘   └──┘     └─┘       └────┘└──┘└┘
typ                             └──┘  └─┘   └──┘    └─┘       └────┘└──┘└┘
doc    └──┘                     └──┘  └─┘   └──┘      └─┘       └────┘└──┘└┘
txt                                                             └────┘    └┘
par                                                             └────┘    └┘
pid                                                                     
st                                                             └───────────┘
503  @[simp] theorem tail_cons (a : α) (s) : tail (cons a s) = s := by simp [tail]
id                                          └──┘  └──┘                  └──┘
src                                          └──┘  └──┘               └────┘└──┘└┘
typ                                         └──┘  └──┘            └────┘└──┘└┘
doc    └──┘                                  └──┘  └──┘                └────┘└──┘└┘
txt                                                                    └────┘    └┘
par                                                                    └────┘    └┘
pid                                                                            
st                                                                    └───────────┘
504  @[simp] theorem tail_think (s : wseq α) : tail (think s) = (tail s).think := by simp [tail]
id                                   └──┘     └──┘  └───┘     └──┘  └───┘              └──┘
src                                  └──┘      └──┘  └───┘      └──┘   └───┘        └────┘└──┘└─
typ                                  └──┘     └──┘  └───┘     └──┘  └───┘        └────┘└──┘└─
doc    └──┘                          └──┘      └──┘  └───┘       └──┘   └───┘        └────┘└──┘└─
txt                                                                                  └────┘    └─
par                                                                                  └────┘    └─
pid                                                                                          
st                                                                                  └────────────
505  
src  
typ  
doc  
txt  
par  
pid  
st   
506  @[simp] theorem dropn_nil (n) :
doc    └──┘
507    drop (nil : wseq α) n = nil := by induction n; simp [*, drop]
id     └──┘  └─┘   └──┘     └─┘                            └──┘
src    └──┘  └─┘   └──┘       └─┘       └────────┘   └───────┘└──┘└┘
typ    └──┘  └─┘   └──┘     └─┘       └────────┘  └───────┘└──┘└┘
doc    └──┘  └─┘   └──┘        └─┘       └────────┘   └───────┘└──┘└┘
txt                                      └────────┘   └───────┘    └┘
par                                      └────────┘   └───────┘    └┘
pid                                                      └──┘    
st                                      └───────────────────────────┘
508  @[simp] theorem dropn_cons (a : α) (s) (n) :
id                                   
typ                                  
doc    └──┘
509    drop (cons a s) (n+1) = drop s n := by induction n; simp [*, drop]
id     └──┘  └──┘         └──┘                              └──┘
src    └──┘  └──┘            └──┘           └────────┘   └───────┘└──┘└┘
typ    └──┘  └──┘         └──┘         └────────┘  └───────┘└──┘└┘
doc    └──┘  └──┘              └──┘           └────────┘   └───────┘└──┘└┘
txt                                           └────────┘   └───────┘    └┘
par                                           └────────┘   └───────┘    └┘
pid                                                           └──┘    
st                                           └───────────────────────────┘
510  @[simp] theorem dropn_think (s : wseq α) (n) :
id                                    └──┘ 
src                                   └──┘
typ                                   └──┘ 
doc    └──┘                           └──┘
511    drop (think s) n = (drop s n).think := by induction n; simp [*, drop]
id     └──┘  └───┘      └──┘   └───┘                             └──┘
src    └──┘  └───┘        └──┘     └───┘        └────────┘   └───────┘└──┘└─
typ    └──┘  └───┘      └──┘   └───┘        └────────┘  └───────┘└──┘└─
doc    └──┘  └───┘         └──┘     └───┘        └────────┘   └───────┘└──┘└─
txt                                              └────────┘   └───────┘    └─
par                                              └────────┘   └───────┘    └─
pid                                                              └──┘    
st                                              └────────────────────────────
512  
src  
typ  
doc  
txt  
par  
pid  
st   
513  theorem dropn_add (s : wseq α) (m) : ∀ n, drop s (m + n) = drop (drop s m) n
id                          └──┘             └──┘        └──┘  └──┘    
src                         └──┘               └──┘           └──┘  └──┘
typ                         └──┘             └──┘        └──┘  └──┘    
doc                         └──┘               └──┘             └──┘  └──┘
514  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
515  | (n+1) := congr_arg tail (dropn_add n)
id            └───────┘ └──┘  └───────┘
src            └───────┘ └──┘
typ           └───────┘ └──┘  └───────┘
doc                       └──┘
516  
517  theorem dropn_tail (s : wseq α) (n) : drop (tail s) n = drop s (n + 1) :=
id                           └──┘         └──┘  └──┘     └──┘    
src                          └──┘          └──┘  └──┘       └──┘      
typ                          └──┘         └──┘  └──┘     └──┘    
doc                          └──┘          └──┘  └──┘        └──┘
518  by rw add_comm; symmetry; apply dropn_add
id         └──────┘                  └───────┘
src     └─┘└──────┘  └──────┘  └────┘└───────┘
typ     └─┘└──────┘  └──────┘  └────┘└───────┘
doc     └─┘          └──────┘  └────┘         
txt     └─┘          └──────┘  └────┘         
par     └─┘          └──────┘  └────┘         
pid                                         
st     └───────────────────────────────────────
519  
src  
typ  
doc  
txt  
par  
pid  
st   
520  theorem nth_add (s : wseq α) (m n) : nth s (m + n) = nth (drop s m) n :=
id                        └──┘           └─┘        └─┘  └──┘    
src                       └──┘            └─┘           └─┘  └──┘
typ                       └──┘           └─┘        └─┘  └──┘    
doc                       └──┘            └─┘             └─┘  └──┘
521  congr_arg head (dropn_add _ _ _)
id   └───────┘ └──┘  └───────┘
src  └───────┘ └──┘  └───────┘
typ  └───────┘ └──┘  └───────┘
doc            └──┘
522  
523  theorem nth_tail (s : wseq α) (n) : nth (tail s) n = nth s (n + 1) :=
id                         └──┘         └─┘  └──┘     └─┘    
src                        └──┘          └─┘  └──┘       └─┘      
typ                        └──┘         └─┘  └──┘     └─┘    
doc                        └──┘          └─┘  └──┘        └─┘
524  congr_arg head (dropn_tail _ _)
id   └───────┘ └──┘  └────────┘
src  └───────┘ └──┘  └────────┘
typ  └───────┘ └──┘  └────────┘
doc            └──┘
525  
526  @[simp] theorem join_nil : join nil = (nil : wseq α) := seq.join_nil
id                              └──┘ └─┘   └─┘   └──┘      └──────────┘
src                             └──┘ └─┘   └─┘   └──┘       └──────────┘
typ                             └──┘ └─┘   └─┘   └──┘      └──────────┘
doc    └──┘                     └──┘ └─┘    └─┘   └──┘
527  
528  @[simp] theorem join_think (S : wseq (wseq α)) :
id                                   └──┘  └──┘ 
src                                  └──┘  └──┘
typ                                  └──┘  └──┘ 
doc    └──┘                          └──┘  └──┘
529    join (think S) = think (join S) :=
id     └──┘  └───┘    └───┘  └──┘ 
src    └──┘  └───┘     └───┘  └──┘
typ    └──┘  └───┘    └───┘  └──┘ 
doc    └──┘  └───┘      └───┘  └──┘
530  by { simp [think, join], unfold functor.map, simp [join, seq1.ret] }
id              └───┘  └──┘                             └──┘  └──────┘
src       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──────┘└┘
typ       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──────┘└┘
doc       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──────┘└┘
txt       └────┘     └┘      └────────────────┘  └────┘    └┘        └┘
par       └────┘     └┘      └────────────────┘  └────┘    └┘        └┘
pid                └┘            └──────────┘          └┘        
st     └───────────────────┘└──────────────────┘└──────────────────────┘└┘
531  
532  @[simp] theorem join_cons (s : wseq α) (S) :
id                                  └──┘ 
src                                 └──┘
typ                                 └──┘ 
doc    └──┘                         └──┘
533    join (cons s S) = think (append s (join S)) :=
id     └──┘  └──┘     └───┘  └────┘   └──┘ 
src    └──┘  └──┘       └───┘  └────┘    └──┘
typ    └──┘  └──┘     └───┘  └────┘   └──┘ 
doc    └──┘  └──┘        └───┘  └────┘    └──┘
534  by { simp [think, join], unfold functor.map, simp [join, cons, append] }
id              └───┘  └──┘                             └──┘  └──┘  └────┘
src       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──┘└┘└────┘└┘
typ       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──┘└┘└────┘└┘
doc       └────┘└───┘└┘└──┘  └────────────────┘  └────┘└──┘└┘└──┘└┘└────┘└┘
txt       └────┘     └┘      └────────────────┘  └────┘    └┘    └┘      └┘
par       └────┘     └┘      └────────────────┘  └────┘    └┘    └┘      └┘
pid                └┘            └──────────┘          └┘    └┘      
st     └───────────────────┘└──────────────────┘└──────────────────────────┘└┘
535  
536  @[simp] theorem nil_append (s : wseq α) : append nil s = s := seq.nil_append _
id                                   └──┘     └────┘ └─┘       └────────────┘
src                                  └──┘      └────┘ └─┘         └────────────┘
typ                                  └──┘     └────┘ └─┘       └────────────┘
doc    └──┘                          └──┘      └────┘ └─┘
537  
538  @[simp] theorem cons_append (a : α) (s t) :
id                                    
typ                                   
doc    └──┘
539    append (cons a s) t = cons a (append s t) := seq.cons_append _ _ _
id     └────┘  └──┘      └──┘   └────┘       └─────────────┘
src    └────┘  └──┘         └──┘    └────┘         └─────────────┘
typ    └────┘  └──┘      └──┘   └────┘       └─────────────┘
doc    └────┘  └──┘          └──┘    └────┘
540  
541  @[simp] theorem think_append (s t : wseq α) :
id                                       └──┘ 
src                                      └──┘
typ                                      └──┘ 
doc    └──┘                              └──┘
542    append (think s) t = think (append s t) := seq.cons_append _ _ _
id     └────┘  └───┘     └───┘  └────┘       └─────────────┘
src    └────┘  └───┘       └───┘  └────┘         └─────────────┘
typ    └────┘  └───┘     └───┘  └────┘       └─────────────┘
doc    └────┘  └───┘        └───┘  └────┘
543  
544  @[simp] theorem append_nil (s : wseq α) : append s nil = s := seq.append_nil _
id                                   └──┘     └────┘  └─┘      └────────────┘
src                                  └──┘      └────┘   └─┘       └────────────┘
typ                                  └──┘     └────┘  └─┘      └────────────┘
doc    └──┘                          └──┘      └────┘   └─┘
545  
546  @[simp] theorem append_assoc (s t u : wseq α) :
id                                         └──┘ 
src                                        └──┘
typ                                        └──┘ 
doc    └──┘                                └──┘
547    append (append s t) u = append s (append t u) := seq.append_assoc _ _ _
id     └────┘  └────┘      └────┘   └────┘       └──────────────┘
src    └────┘  └────┘         └────┘    └────┘         └──────────────┘
typ    └────┘  └────┘      └────┘   └────┘       └──────────────┘
doc    └────┘  └────┘          └────┘    └────┘
548  
549  @[simp] def tail.aux : option (α × wseq α) → computation (option (α × wseq α))
id                          └────┘    └──┘    └─────────┘  └────┘    └──┘ 
src                         └────┘     └──┘      └─────────┘  └────┘     └──┘
typ                         └────┘    └──┘    └─────────┘  └────┘    └──┘ 
doc    └──┘                             └──┘      └─────────┘              └──┘
550  | none          := return none
id     └──┘             └────┘ └──┘
src    └──┘             └────┘ └──┘
typ    └──┘             └────┘ └──┘
doc                     └────┘
551  | (some (a, s)) := destruct s
id      └──┘          └──────┘
src     └──┘           └──────┘
typ     └──┘          └──────┘
doc                     └──────┘
552  
553  theorem destruct_tail (s : wseq α) :
id                              └──┘ 
src                             └──┘
typ                             └──┘ 
doc                             └──┘
554    destruct (tail s) = destruct s >>= tail.aux :=
id     └──────┘  └──┘    └──────┘  └─┘ └──────┘
src    └──────┘  └──┘     └──────┘   └─┘ └──────┘
typ    └──────┘  └──┘    └──────┘  └─┘ └──────┘
doc    └──────┘  └──┘      └──────┘
555  begin
st   └─────
556    dsimp [tail], simp, rw [← bind_pure_comp_eq_map, is_lawful_monad.bind_assoc],
id            └──┘               └───────────────────┘  └────────────────────────┘
src    └─────┘└──┘  └──┘  └────┘└───────────────────┘└┘└────────────────────────┘
typ    └─────┘└──┘  └──┘  └────┘└───────────────────┘└┘└────────────────────────┘
doc    └─────┘└──┘  └──┘  └────┘                     └┘                          
txt    └─────┘      └──┘  └────┘                     └┘                          
par    └─────┘      └──┘  └────┘                     └┘                          
pid                       └──┘                     └┘                          
st   ─────────────┘└────┘└───────────────────────────┘└──────────────────────────┘└──
557    apply congr_arg, funext o,
id           └───────┘
src    └────┘└───────┘  └──────┘
typ    └────┘└───────┘  └──────┘
doc    └────┘           └──────┘
txt    └────┘           └──────┘
par    └────┘           └──────┘
pid                          └┘
st   ────────────────┘└────────┘└─
558    rcases o with _|⟨a, s⟩;
id            
src    └─────┘ └────────────┘
typ    └─────┘└────────────┘
doc    └─────┘ └────────────┘
txt    └─────┘ └────────────┘
par    └─────┘ └────────────┘
pid           └────────────┘
st   ──────────────────────────
559    apply (@pure_bind computation _ _ _ _ _ _).trans _; simp
id             └───────┘ └─────────┘
src    └────┘  └───────┘└─────────┘└───────────────────┘  └───┘
typ    └────┘  └───────┘└─────────┘└───────────────────┘  └───┘
doc    └────┘           └─────────┘└───────────────────┘  └───┘
txt    └────┘                      └───────────────────┘  └───┘
par    └────┘                      └───────────────────┘  └───┘
pid                               └───────────────────┘      
st   ──────────────────────────────────────────────────────────┘
560  end
st   └─┘
561  
562  @[simp] def drop.aux : ℕ → option (α × wseq α) → computation (option (α × wseq α))
id                            └────┘    └──┘     └─────────┘  └────┘    └──┘ 
src                            └────┘     └──┘      └─────────┘  └────┘     └──┘
typ                           └────┘    └──┘     └─────────┘  └────┘    └──┘ 
doc    └──┘                                 └──┘      └─────────┘              └──┘
563  | 0     := return
id              └────┘
src             └────┘
typ             └────┘
doc             └────┘
564  | (n+1) := λ a, tail.aux a >>= drop.aux n
id                └──────┘  └─┘ └──────┘
src                 └──────┘   └─┘
typ               └──────┘  └─┘ └──────┘
565  
566  theorem drop.aux_none : ∀ n, @drop.aux α n none = return none
id                                └──────┘   └──┘  └────┘ └──┘
src                                └──────┘     └──┘  └────┘ └──┘
typ                               └──────┘   └──┘  └────┘ └──┘
doc                                                    └────┘
567  | 0     := rfl
id              └─┘
src             └─┘
typ             └─┘
568  | (n+1) := show computation.bind (return none) (drop.aux n) = return none,
id                 └──────────────┘  └────┘ └──┘   └──────┘     └────┘ └──┘
src                 └──────────────┘  └────┘ └──┘   └──────┘     └────┘ └──┘
typ                └──────────────┘  └────┘ └──┘   └──────┘     └────┘ └──┘
doc                  └──────────────┘  └────┘                      └────┘
569             by rw [ret_bind, drop.aux_none]
id                     └──────┘  └───────────┘
src                └──┘└──────┘└┘             └─
typ                └──┘└──────┘└┘└───────────┘└─
doc                └──┘        └┘             └─
txt                └──┘        └┘             └─
par                └──┘        └┘             └─
pid                  └┘        └┘             
st                └───────────┘└─────────────┘
570  
src  
typ  
doc  
txt  
par  
pid  
st   
571  theorem destruct_dropn :
572    ∀ (s : wseq α) n, destruct (drop s n) = destruct s >>= drop.aux n
id           └──┘     └──────┘  └──┘     └──────┘  └─┘ └──────┘ 
src           └──┘       └──────┘  └──┘       └──────┘   └─┘ └──────┘
typ          └──┘     └──────┘  └──┘     └──────┘  └─┘ └──────┘ 
doc           └──┘       └──────┘  └──┘        └──────┘
573  | s 0     := (bind_ret' _).symm
id                 └───────┘   └──┘
src                └───────┘   └──┘
typ                └───────┘   └──┘
574  | s (n+1) := by rw [← dropn_tail, destruct_dropn _ n,
id                        └────────┘  └────────────┘   
src                 └────┘└────────┘└┘              └─┘ └─
typ                 └────┘└────────┘└┘└────────────┘└─┘└─
doc                  └────┘          └┘              └─┘ └─
txt                  └────┘          └┘              └─┘ └─
par                  └────┘          └┘              └─┘ └─
pid                    └──┘          └┘              └─┘ └─
st                  └───────────────┘└──────────────────┘└─
575    destruct_tail, is_lawful_monad.bind_assoc]; refl
id     └───────────┘  └────────────────────────┘
src  ─┘└───────────┘└┘└────────────────────────┘  └────
typ  ─┘└───────────┘└┘└────────────────────────┘  └────
doc  ─┘             └┘                            └────
txt  ─┘             └┘                            └────
par  ─┘             └┘                            └────
pid  ─┘             └┘                                
st   ──────────────┘└──────────────────────────┘└──────
576  
src  
typ  
doc  
txt  
par  
pid  
st   
577  theorem head_terminates_of_head_tail_terminates (s : wseq α) [T : terminates (head (tail s))] :
id                                                        └──┘        └────────┘  └──┘  └──┘ 
src                                                       └──┘         └────────┘  └──┘  └──┘
typ                                                       └──┘        └────────┘  └──┘  └──┘ 
doc                                                       └──┘         └────────┘  └──┘  └──┘
578    terminates (head s) :=
id     └────────┘  └──┘ 
src    └────────┘  └──┘
typ    └────────┘  └──┘ 
doc    └────────┘  └──┘
579  (head_terminates_iff _).2 $ begin
id    └─────────────────┘   
src   └─────────────────┘   
typ   └─────────────────┘   
st                               └─────
580    cases (head_terminates_iff _).1 T with a h,
id            └─────────────────┘      
src    └────┘ └─────────────────┘└────┘ └───────┘
typ    └────┘ └─────────────────┘└────┘└───────┘
doc    └────┘                    └────┘ └───────┘
txt    └────┘                    └────┘ └───────┘
par    └────┘                    └────┘ └───────┘
pid                             └────┘ └───────┘
st   ───────────────────────────────────────────┘└─
581    simp [tail] at h,
id           └──┘
src    └────┘└──┘└────┘
typ    └────┘└──┘└────┘
doc    └────┘└──┘└────┘
txt    └────┘    └────┘
par    └────┘    └────┘
pid            └──┘
st   ─────────────────┘└─
582    rcases exists_of_mem_bind h with ⟨s', h1, h2⟩,
id            └────────────────┘ 
src    └─────┘└────────────────┘ └────────────────┘
typ    └─────┘└────────────────┘└────────────────┘
doc    └─────┘                   └────────────────┘
txt    └─────┘                   └────────────────┘
par    └─────┘                   └────────────────┘
pid                             └────────────────┘
st   ──────────────────────────────────────────────┘└─
583    unfold functor.map at h1,
src    └──────────────────────┘
typ    └──────────────────────┘
doc    └──────────────────────┘
txt    └──────────────────────┘
par    └──────────────────────┘
pid          └──────────┘└────┘
st   ─────────────────────────┘└─
584    exact let ⟨t, h3, h4⟩ := exists_of_mem_map h1 in terminates_of_mem h3
id                   └┘         └───────────────┘ └┘    └───────────────┘
src    └────┘     └┘  └┘  └───┘└───────────────┘  └──┘└───────────────┘  
typ    └────┘     └┘└┘└┘  └───┘└───────────────┘└┘└──┘└───────────────┘  
doc    └────┘     └┘  └┘  └───┘                   └──┘                   
txt    └────┘     └┘  └┘  └───┘                   └──┘                   
par    └────┘     └┘  └┘  └───┘                   └──┘                   
pid              └┘  └┘  └───┘                   └──┘                   
st   ───────────────────────────────────────────────────────────────────────┘
585  end
st   └─┘
586  
587  theorem destruct_some_of_destruct_tail_some {s : wseq α} {a}
id                                                    └──┘ 
src                                                   └──┘
typ                                                   └──┘ 
doc                                                   └──┘
588    (h : some a ∈ destruct (tail s)) : ∃ a', some a' ∈ destruct s :=
id          └──┘   └──────┘  └──┘       └┘ └──┘ └┘  └──────┘ 
src         └──┘    └──────┘  └──┘           └──┘     └──────┘
typ         └──┘   └──────┘  └──┘       └┘ └──┘ └┘  └──────┘ 
doc                  └──────┘  └──┘                       └──────┘
589  begin
st   └─────
590    unfold tail functor.map at h, simp at h,
src    └──────────────────────────┘  └───────┘
typ    └──────────────────────────┘  └───────┘
doc    └──────────────────────────┘  └───────┘
txt    └──────────────────────────┘  └───────┘
par    └──────────────────────────┘  └───────┘
pid          └───────────────┘└───┘      └──┘
st   ─────────────────────────────┘└─────────┘└─
591    rcases exists_of_mem_bind h with ⟨t, tm, td⟩, clear h,
id            └────────────────┘ 
src    └─────┘└────────────────┘ └───────────────┘  └─────┘
typ    └─────┘└────────────────┘└───────────────┘  └─────┘
doc    └─────┘                   └───────────────┘  └─────┘
txt    └─────┘                   └───────────────┘  └─────┘
par    └─────┘                   └───────────────┘  └─────┘
pid                             └───────────────┘       └┘
st   ─────────────────────────────────────────────┘└───────┘└─
592    rcases exists_of_mem_map tm with ⟨t', ht', ht2⟩, clear tm,
id            └───────────────┘ └┘
src    └─────┘└───────────────┘  └──────────────────┘  └──────┘
typ    └─────┘└───────────────┘└┘└──────────────────┘  └──────┘
doc    └─────┘                   └──────────────────┘  └──────┘
txt    └─────┘                   └──────────────────┘  └──────┘
par    └─────┘                   └──────────────────┘  └──────┘
pid                             └──────────────────┘       └─┘
st   ────────────────────────────────────────────────┘└────────┘└─
593    cases t' with t'; rw ←ht2 at td; simp at td,
id           └┘              └─┘
src    └────┘  └──────┘  └──┘   └────┘  └────────┘
typ    └────┘└┘└──────┘  └──┘└─┘└────┘  └────────┘
doc    └────┘  └──────┘  └──┘   └────┘  └────────┘
txt    └────┘  └──────┘  └──┘   └────┘  └────────┘
par    └────┘  └──────┘  └──┘   └────┘  └────────┘
pid           └──────┘    └┘   └────┘      └───┘
st   ────────────────────────────────────────────┘└─
594    { have := mem_unique td (ret_mem _), contradiction },
id               └────────┘ └┘  └─────┘
src      └──────┘└────────┘   └─────┘└─┘  └────────────┘
typ      └──────┘└────────┘└┘ └─────┘└─┘  └────────────┘
doc      └──────┘                    └─┘  └────────────┘
txt      └──────┘                    └─┘  └────────────┘
par      └──────┘                    └─┘  └────────────┘
pid      └───┘└─┘                    └─┘               
st   ───┘└───────────────────────────────┘└──────────────┘└┘
595    { exact ⟨_, ht'⟩ }
id                 └─┘
src      └────┘ └─┘   └┘
typ      └────┘ └─┘└─┘└┘
doc      └────┘ └─┘   └┘
txt      └────┘ └─┘   └┘
par      └────┘ └─┘   └┘
pid            └─┘   
st   ──────────────────┘└─
596  end
st   ──┘
597  
598  theorem head_some_of_head_tail_some {s : wseq α} {a}
id                                            └──┘ 
src                                           └──┘
typ                                           └──┘ 
doc                                           └──┘
599    (h : some a ∈ head (tail s)) : ∃ a', some a' ∈ head s :=
id          └──┘   └──┘  └──┘       └┘ └──┘ └┘  └──┘ 
src         └──┘    └──┘  └──┘           └──┘     └──┘
typ         └──┘   └──┘  └──┘       └┘ └──┘ └┘  └──┘ 
doc                  └──┘  └──┘                       └──┘
600  begin
st   └─────
601    unfold head at h,
src    └──────────────┘
typ    └──────────────┘
doc    └──────────────┘
txt    └──────────────┘
par    └──────────────┘
pid          └───┘└───┘
st   ─────────────────┘└─
602    rcases exists_of_mem_map h with ⟨o, md, e⟩, clear h,
id            └───────────────┘ 
src    └─────┘└───────────────┘ └──────────────┘  └─────┘
typ    └─────┘└───────────────┘└──────────────┘  └─────┘
doc    └─────┘                  └──────────────┘  └─────┘
txt    └─────┘                  └──────────────┘  └─────┘
par    └─────┘                  └──────────────┘  └─────┘
pid                            └──────────────┘       └┘
st   ───────────────────────────────────────────┘└───────┘└─
603    cases o with o; injection e with h', clear e h',
id                              
src    └────┘ └─────┘  └────────┘ └──────┘  └────────┘
typ    └────┘└─────┘  └────────┘└──────┘  └────────┘
doc    └────┘ └─────┘  └────────┘ └──────┘  └────────┘
txt    └────┘ └─────┘  └────────┘ └──────┘  └────────┘
par    └────┘ └─────┘  └────────┘ └──────┘  └────────┘
pid          └─────┘            └──────┘       └───┘
st   ────────────────────────────────────┘└──────────┘└─
604    cases destruct_some_of_destruct_tail_some md with a am,
id           └─────────────────────────────────┘ └┘
src    └────┘└─────────────────────────────────┘  └────────┘
typ    └────┘└─────────────────────────────────┘└┘└────────┘
doc    └────┘                                     └────────┘
txt    └────┘                                     └────────┘
par    └────┘                                     └────────┘
pid                                              └────────┘
st   ───────────────────────────────────────────────────────┘└─
605    exact ⟨_, mem_map ((<$>) (@prod.fst α (wseq α))) am⟩
id               └─────┘         └──────┘    └──┘     └┘
src    └────┘ └─┘└─────┘ └───┘  └──────┘  └──┘ └──┘  └┘
typ    └────┘ └─┘└─────┘ └───┘  └──────┘  └──┘└──┘└┘└┘
doc    └────┘ └─┘         └───┘            └──┘ └──┘  └┘
txt    └────┘ └─┘         └───┘                 └──┘  └┘
par    └────┘ └─┘         └───┘                 └──┘  └┘
pid          └─┘         └───┘                 └──┘  
st   ──────────────────────────────────────────────────────┘
606  end
st   └─┘
607  
608  theorem head_some_of_nth_some {s : wseq α} {a n}
id                                      └──┘ 
src                                     └──┘
typ                                     └──┘ 
doc                                     └──┘
609    (h : some a ∈ nth s n) : ∃ a', some a' ∈ head s :=
id          └──┘   └─┘       └┘ └──┘ └┘  └──┘ 
src         └──┘    └─┘            └──┘     └──┘
typ         └──┘   └─┘       └┘ └──┘ └┘  └──┘ 
doc                  └─┘                        └──┘
610  begin
st   └─────
611    revert a, induction n with n IH; intros,
id                         
src    └──────┘  └────────┘ └────────┘  └────┘
typ    └──────┘  └────────┘└────────┘  └────┘
doc    └──────┘  └────────┘ └────────┘  └────┘
txt    └──────┘  └────────┘ └────────┘  └────┘
par    └──────┘  └────────┘ └────────┘  └────┘
pid          └┘            └───────┘
st   ─────────┘└─────────────────────────────┘└─
612    exacts [⟨_, h⟩, let ⟨a', h'⟩ := head_some_of_head_tail_some h in IH h']
id                             └┘     └─────────────────────────┘     └┘
src    └──────┘ └─┘ └─┘      └┘  └───┘└─────────────────────────┘ └──┘    └┘
typ    └──────┘ └─┘└─┘      └┘└┘└───┘└─────────────────────────┘└──┘└┘  └┘
doc    └──────┘ └─┘ └─┘      └┘  └───┘                            └──┘    └┘
txt    └──────┘ └─┘ └─┘      └┘  └───┘                            └──┘    └┘
par    └──────┘ └─┘ └─┘      └┘  └───┘                            └──┘    └┘
pid          └┘ └─┘ └─┘      └┘  └───┘                            └──┘    
st   ─────────────────────────────────────────────────────────────────────────┘
613  end
st   └─┘
614  
615  instance productive_tail (s : wseq α) [productive s] : productive (tail s) :=
id                                 └──┘    └────────┘     └────────┘  └──┘ 
src                                └──┘     └────────┘      └────────┘  └──┘
typ                                └──┘    └────────┘     └────────┘  └──┘ 
doc                                └──┘     └────────┘      └────────┘  └──┘
616  λ n, by rw [nth_tail]; apply_instance
id              └──────┘
src          └──┘└──────┘  └──────────────
typ         └──┘└──────┘  └──────────────
doc          └──┘          └──────────────
txt          └──┘          └──────────────
par          └──┘          └──────────────
pid            └┘                        
st          └───────────┘└────────────────
617  
src  
typ  
doc  
txt  
par  
pid  
st   
618  instance productive_dropn (s : wseq α) [productive s] (n) : productive (drop s n) :=
id                                  └──┘    └────────┘         └────────┘  └──┘  
src                                 └──┘     └────────┘          └────────┘  └──┘
typ                                 └──┘    └────────┘         └────────┘  └──┘  
doc                                 └──┘     └────────┘          └────────┘  └──┘
619  λ m, by rw [←nth_add]; apply_instance
id               └─────┘
src          └───┘└─────┘  └──────────────
typ         └───┘└─────┘  └──────────────
doc          └───┘         └──────────────
txt          └───┘         └──────────────
par          └───┘         └──────────────
pid            └─┘                       
st          └───────────┘└────────────────
620  
src  
typ  
doc  
txt  
par  
pid  
st   
621  /-- Given a productive weak sequence, we can collapse all the `think`s to
622    produce a sequence. -/
623  def to_seq (s : wseq α) [productive s] : seq α :=
id                   └──┘    └────────┘     └─┘ 
src                  └──┘     └────────┘      └─┘
typ                  └──┘    └────────┘     └─┘ 
doc                  └──┘     └────────┘      └─┘
624  ⟨λ n, (nth s n).get, λn h,
id         └─┘   └─┘     
src         └─┘     └─┘
typ        └─┘   └─┘     
doc         └─┘     └─┘
625  begin
st   └─────
626    cases e : computation.get (nth s (n + 1)), {assumption},
id               └─────────────┘  └─┘    
src    └────┘ └─┘└─────────────┘ └─┘   └──┘   └────────┘
typ    └────┘ └─┘└─────────────┘ └─┘ └──┘   └────────┘
doc    └────┘ └─┘└─────────────┘ └─┘    └──┘   └────────┘
txt    └────┘ └─┘                       └──┘   └────────┘
par    └────┘ └─┘                       └──┘   └────────┘
pid          └─┘                       └──┘
st   ──────────────────────────────────────────┘└───────────┘└┘
627    have := mem_of_get_eq _ e,
id             └───────────┘   
src    └──────┘└───────────┘└─┘
typ    └──────┘└───────────┘└─┘
doc    └──────┘             └─┘
txt    └──────┘             └─┘
par    └──────┘             └─┘
pid    └───┘└─┘             └─┘
st   ──────────────────────────┘└─
628    simp [nth] at this h, cases head_some_of_head_tail_some this with a' h',
id           └─┘                   └─────────────────────────┘ └──┘
src    └────┘└─┘└─────────┘  └────┘└─────────────────────────┘    └─────────┘
typ    └────┘└─┘└─────────┘  └────┘└─────────────────────────┘└──┘└─────────┘
doc    └────┘└─┘└─────────┘  └────┘                               └─────────┘
txt    └────┘   └─────────┘  └────┘                               └─────────┘
par    └────┘   └─────────┘  └────┘                               └─────────┘
pid           └───────┘                                      └─────────┘
st   ─────────────────────┘└─────────────────────────────────────────────────┘└─
629    have := mem_unique h' (@mem_of_get_eq _ _ _ _ h),
id             └────────┘ └┘   └───────────┘         
src    └──────┘└────────┘    └───────────┘└───────┘ 
typ    └──────┘└────────┘└┘  └───────────┘└───────┘
doc    └──────┘                           └───────┘ 
txt    └──────┘                           └───────┘ 
par    └──────┘                           └───────┘ 
pid    └───┘└─┘                           └───────┘ 
st   ─────────────────────────────────────────────────┘└─
630    contradiction
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid                 
st   ───────────────┘
631  end⟩
st   └─┘
632  
633  theorem nth_terminates_le {s : wseq α} {m n} (h : m ≤ n) : terminates (nth s n) → terminates (nth s m) :=
id                                  └──┘                    └────────┘  └─┘      └────────┘  └─┘  
src                                 └──┘                       └────────┘  └─┘        └────────┘  └─┘
typ                                 └──┘                    └────────┘  └─┘      └────────┘  └─┘  
doc                                 └──┘                        └────────┘  └─┘        └────────┘  └─┘
634  by induction h with m' h IH; [exact id,
id                                     └┘
src     └────────┘ └───────────┘  └────┘└┘
typ     └────────┘└───────────┘  └────┘└┘
doc     └────────┘ └───────────┘   └────┘
txt     └────────┘ └───────────┘   └────┘
par     └────────┘ └───────────┘   └────┘
pid               └──────────┘        
st     └─────────────────────────────────────
635    exact λ T, IH (@head_terminates_of_head_tail_terminates _ _ T)]
id                └┘   └─────────────────────────────────────┘
src    └────┘ └──┘    └─────────────────────────────────────┘└───┘ 
typ    └────┘ └──┘└┘  └─────────────────────────────────────┘└───┘ 
doc    └────┘ └──┘                                           └───┘ 
txt    └────┘ └──┘                                           └───┘ 
par    └────┘ └──┘                                           └───┘ 
pid          └──┘                                           └───┘ 
st   ────────────────────────────────────────────────────────────────┘
636  
637  theorem head_terminates_of_nth_terminates {s : wseq α} {n} : terminates (nth s n) → terminates (head s) :=
id                                                  └──┘         └────────┘  └─┘      └────────┘  └──┘ 
src                                                 └──┘          └────────┘  └─┘        └────────┘  └──┘
typ                                                 └──┘         └────────┘  └─┘      └────────┘  └──┘ 
doc                                                 └──┘          └────────┘  └─┘        └────────┘  └──┘
638  nth_terminates_le (nat.zero_le n)
id   └───────────────┘  └─────────┘ 
src  └───────────────┘  └─────────┘
typ  └───────────────┘  └─────────┘ 
639  
640  theorem destruct_terminates_of_nth_terminates {s : wseq α} {n} (T : terminates (nth s n)) : terminates (destruct s) :=
id                                                      └──┘            └────────┘  └─┘       └────────┘  └──────┘ 
src                                                     └──┘             └────────┘  └─┘         └────────┘  └──────┘
typ                                                     └──┘            └────────┘  └─┘       └────────┘  └──────┘ 
doc                                                     └──┘             └────────┘  └─┘         └────────┘  └──────┘
641  (head_terminates_iff _).1 $ head_terminates_of_nth_terminates T
id    └─────────────────┘       └───────────────────────────────┘ 
src   └─────────────────┘       └───────────────────────────────┘
typ   └─────────────────┘       └───────────────────────────────┘ 
642  
643  theorem mem_rec_on {C : wseq α → Prop} {a s} (M : a ∈ s)
id                           └──┘                       
src                          └──┘                        
typ                          └──┘                       
doc                          └──┘
644    (h1 : ∀ b s', (a = b ∨ C s') → C (cons b s'))
id              └┘        └┘      └──┘  └┘
src                                    └──┘
typ             └┘        └┘      └──┘  └┘
doc                                      └──┘
645    (h2 : ∀ s, C s → C (think s)) : C s :=
id                     └───┘       
src                        └───┘
typ                    └───┘       
doc                        └───┘
646  begin
st   └─────
647    apply seq.mem_rec_on M,
id           └────────────┘ 
src    └────┘└────────────┘
typ    └────┘└────────────┘
doc    └────┘              
txt    └────┘              
par    └────┘              
pid                       
st   ───────────────────────┘└─
648    intros o s' h, cases o with b,
id                          
src    └───────────┘  └────┘ └─────┘
typ    └───────────┘  └────┘└─────┘
doc    └───────────┘  └────┘ └─────┘
txt    └───────────┘  └────┘ └─────┘
par    └───────────┘  └────┘ └─────┘
pid          └─────┘        └─────┘
st   ──────────────┘└──────────────┘└─
649    { apply h2, cases h, {contradiction}, {assumption} },
id                       
src      └────┘    └────┘    └───────────┘    └────────┘
typ      └────┘    └────┘   └───────────┘    └────────┘
doc      └────┘    └────┘    └───────────┘    └────────┘
txt      └────┘    └────┘    └───────────┘    └────────┘
par      └────┘    └────┘    └───────────┘    └────────┘
pid                    
st   ───┘└──────┘└───────┘└──────────────┘└┘└──────────┘└──┘
650    { apply h1, apply or.imp_left _ h, intro h, injection h }
id                       └─────────┘                        
src      └────┘    └────┘└─────────┘└─┘   └─────┘  └────────┘ 
typ      └────┘    └────┘└─────────┘└─┘  └─────┘  └────────┘
doc      └────┘    └────┘           └─┘   └─────┘  └────────┘ 
txt      └────┘    └────┘           └─┘   └─────┘  └────────┘ 
par      └────┘    └────┘           └─┘   └─────┘  └────────┘ 
pid                               └─┘        └┘            
st   ───────────┘└─────────────────────┘└───────┘└────────────┘└─
651  end
st   ──┘
652  
653  @[simp] theorem mem_think (s : wseq α) (a) : a ∈ think s ↔ a ∈ s :=
id                                  └──┘           └───┘     
src                                 └──┘             └───┘      
typ                                 └──┘           └───┘     
doc    └──┘                         └──┘              └───┘
654  begin
st   └─────
655    cases s with f al,
id           
src    └────┘ └────────┘
typ    └────┘└────────┘
doc    └────┘ └────────┘
txt    └────┘ └────────┘
par    └────┘ └────────┘
pid          └────────┘
st   ──────────────────┘└─
656    change some (some a) ∈ some none :: f ↔ some (some a) ∈ f,
id                                └──┘ └┘           └──┘     
src    └─────┘          └┘    └──┘└┘       └──┘ └┘ 
typ    └─────┘          └┘    └──┘└┘       └──┘└┘ 
doc    └─────┘          └┘                       └┘ 
txt    └─────┘          └┘                       └┘ 
par    └─────┘          └┘                       └┘ 
pid                    └┘                       └┘ 
st   ──────────────────────────────────────────────────────────┘└─
657    constructor; intro h,
src    └─────────┘  └─────┘
typ    └─────────┘  └─────┘
doc    └─────────┘  └─────┘
txt    └─────────┘  └─────┘
par    └─────────┘  └─────┘
pid                      └┘
st   ─────────────────────┘└─
658    { apply (stream.eq_or_mem_of_mem_cons h).resolve_left,
id              └──────────────────────────┘ 
src      └────┘ └──────────────────────────┘ └────────────┘
typ      └────┘ └──────────────────────────┘└────────────┘
doc      └────┘                              └────────────┘
txt      └────┘                              └────────────┘
par      └────┘                              └────────────┘
pid                                         └───────────┘
st   ───┘└─────────────────────────────────────────────────┘└─
659      intro, injections },
src      └───┘  └─────────┘
typ      └───┘  └─────────┘
doc      └───┘  └─────────┘
txt      └───┘  └─────────┘
par      └───┘  └─────────┘
pid                       
st   ────────┘└───────────┘└┘
660    { apply stream.mem_cons_of_mem _ h }
id             └────────────────────┘   
src      └────┘└────────────────────┘└─┘ 
typ      └────┘└────────────────────┘└─┘
doc      └────┘                      └─┘ 
txt      └────┘                      └─┘ 
par      └────┘                      └─┘ 
pid                                 └─┘ 
st   ────────────────────────────────────┘└─
661  end
st   ──┘
662  
663  theorem eq_or_mem_iff_mem {s : wseq α} {a a' s'} :
id                                  └──┘ 
src                                 └──┘
typ                                 └──┘ 
doc                                 └──┘
664    some (a', s') ∈ destruct s → (a ∈ s ↔ a = a' ∨ a ∈ s') :=
id     └──┘ └┘  └┘   └──────┘           └┘    └┘
src    └──┘          └──────┘                     
typ    └──┘ └┘  └┘   └──────┘           └┘    └┘
doc                    └──────┘
665  begin
st   └─────
666    generalize e : destruct s = c, intro h,
id                    └──────┘ 
src    └─────────────┘└──────┘     └─────┘
typ    └─────────────┘└──────┘    └─────┘
doc    └─────────────┘└──────┘     └─────┘
txt    └─────────────┘             └─────┘
par    └─────────────┘             └─────┘
pid              └┘└┘                  └┘
st   ──────────────────────────────┘└───────┘└─
667    revert s, apply computation.mem_rec_on h _ (λ c IH, _); intro s;
id                     └────────────────────┘ 
src    └──────┘  └────┘└────────────────────┘ └─┘  └───────┘  └─────┘
typ    └──────┘  └────┘└────────────────────┘└─┘  └───────┘  └─────┘
doc    └──────┘  └────┘                       └─┘  └───────┘  └─────┘
txt    └──────┘  └────┘                       └─┘  └───────┘  └─────┘
par    └──────┘  └────┘                       └─┘  └───────┘  └─────┘
pid          └┘                              └─┘  └───────┘       └┘
st   ─────────┘└────────────────────────────────────────────────────────
668    apply s.cases_on _ (λ x s, _) (λ s, _); intros m;
id           └────────┘
src    └────┘└────────┘└─┘  └───────┘  └────┘  └──────┘
typ    └────┘└────────┘└─┘  └───────┘  └────┘  └──────┘
doc    └────┘          └─┘  └───────┘  └────┘  └──────┘
txt    └────┘          └─┘  └───────┘  └────┘  └──────┘
par    └────┘          └─┘  └───────┘  └────┘  └──────┘
pid                   └─┘  └───────┘  └────┘        └┘
st   ────────────────────────────────────────────────────
669    have := congr_arg computation.destruct m; simp at this;
id             └───────┘ └──────────────────┘ 
src    └──────┘└───────┘└──────────────────┘   └──────────┘
typ    └──────┘└───────┘└──────────────────┘  └──────────┘
doc    └──────┘         └──────────────────┘   └──────────┘
txt    └──────┘                                └──────────┘
par    └──────┘                                └──────────┘
pid    └───┘└─┘                                    └─────┘
st   ──────────────────────────────────────────────────────────
670    cases this with i1 i2,
id           └──┘
src    └────┘    └─────────┘
typ    └────┘└──┘└─────────┘
doc    └────┘    └─────────┘
txt    └────┘    └─────────┘
par    └────┘    └─────────┘
pid             └─────────┘
st   ──────────────────────┘└─
671    { rw [i1, i2],
id           └┘  └┘
src      └──┘  └┘  
typ      └──┘└┘└┘└┘
doc      └──┘  └┘  
txt      └──┘  └┘  
par      └──┘  └┘  
pid        └┘  └┘  
st   ───┘└────┘└──┘└──
672      cases s' with f al,
id             └┘
src      └────┘  └────────┘
typ      └────┘└┘└────────┘
doc      └────┘  └────────┘
txt      └────┘  └────────┘
par      └────┘  └────────┘
pid             └────────┘
st   ─────────────────────┘└─
673      unfold cons has_mem.mem wseq.mem seq.mem seq.cons, simp,
src      └───────────────────────────────────────────────┘  └──┘
typ      └───────────────────────────────────────────────┘  └──┘
doc      └───────────────────────────────────────────────┘  └──┘
txt      └───────────────────────────────────────────────┘  └──┘
par      └───────────────────────────────────────────────┘  └──┘
pid            └─────────────────────────────────────────┘
st   ────────────────────────────────────────────────────┘└────┘└─
674      have h_a_eq_a' : a = a' ↔ some (some a) = some (some a'), {simp},
id                                                      └──┘ └┘
src      └───────────────┘               └┘      └──┘     └──┘
typ      └───────────────┘              └┘      └──┘└┘   └──┘
doc      └───────────────┘               └┘               └──┘
txt      └───────────────┘               └┘               └──┘
par      └───────────────┘               └┘               └──┘
pid      └────────────┘└─┘               └┘            
st   ───────────────────────────────────────────────────────────┘└─────┘└┘
675      rw [h_a_eq_a'],
id           └───────┘
src      └──┘         
typ      └──┘└───────┘
doc      └──┘         
txt      └──┘         
par      └──┘         
pid        └┘         
st   ────────────────┘└──
676      refine ⟨stream.eq_or_mem_of_mem_cons, λo, _⟩,
id               └──────────────────────────┘
src      └─────┘ └──────────────────────────┘└┘ └───┘
typ      └─────┘ └──────────────────────────┘└┘ └───┘
doc      └─────┘                             └┘ └───┘
txt      └─────┘                             └┘ └───┘
par      └─────┘                             └┘ └───┘
pid                                         └┘ └───┘
st   ───────────────────────────────────────────────┘└─
677      { cases o with e m,
id               
src        └────┘ └───────┘
typ        └────┘└───────┘
doc        └────┘ └───────┘
txt        └────┘ └───────┘
par        └────┘ └───────┘
pid              └───────┘
st   ─────────────────────┘└─
678        { rw e, apply stream.mem_cons },
id                      └─────────────┘
src          └─┘   └────┘└─────────────┘
typ          └─┘  └────┘└─────────────┘
doc          └─┘   └────┘               
txt          └─┘   └────┘               
par          └─┘   └────┘               
pid                                   
st   ───────┘└──┘└──────────────────────┘└┘
679        { exact stream.mem_cons_of_mem _ m } } },
id                 └────────────────────┘   
src          └────┘└────────────────────┘└─┘ 
typ          └────┘└────────────────────┘└─┘
doc          └────┘                      └─┘ 
txt          └────┘                      └─┘ 
par          └────┘                      └─┘ 
pid                                     └─┘ 
st   ────────────────────────────────────────┘└────┘
680    { simp, exact IH this }
id                   └┘ └──┘
src      └──┘  └────┘      
typ      └──┘  └────┘└┘└──┘
doc      └──┘  └────┘      
txt      └──┘  └────┘      
par      └──┘  └────┘      
pid                       
st   ───────┘└──────────────┘└─
681  end
st   ──┘
682  
683  @[simp] theorem mem_cons_iff (s : wseq α) (b) {a} : a ∈ cons b s ↔ a = b ∨ a ∈ s :=
id                                     └──┘               └──┘          
src                                    └──┘                 └──┘              
typ                                    └──┘               └──┘          
doc    └──┘                            └──┘                  └──┘
684  eq_or_mem_iff_mem $ by simp [ret_mem]
id   └───────────────┘            └─────┘
src  └───────────────┘      └────┘└─────┘└─
typ  └───────────────┘      └────┘└─────┘└─
doc                         └────┘       └─
txt                         └────┘       └─
par                         └────┘       └─
pid                                    
st                         └───────────────
685  
src  
typ  
doc  
txt  
par  
pid  
st   
686  theorem mem_cons_of_mem {s : wseq α} (b) {a} (h : a ∈ s) : a ∈ cons b s :=
id                                └──┘                        └──┘  
src                               └──┘                            └──┘
typ                               └──┘                        └──┘  
doc                               └──┘                              └──┘
687  (mem_cons_iff _ _).2 (or.inr h)
id    └──────────┘        └────┘ 
src   └──────────┘        └────┘
typ   └──────────┘        └────┘ 
688  
689  theorem mem_cons (s : wseq α) (a) : a ∈ cons a s :=
id                         └──┘           └──┘  
src                        └──┘             └──┘
typ                        └──┘           └──┘  
doc                        └──┘              └──┘
690  (mem_cons_iff _ _).2 (or.inl rfl)
id    └──────────┘        └────┘ └─┘
src   └──────────┘        └────┘ └─┘
typ   └──────────┘        └────┘ └─┘
691  
692  theorem mem_of_mem_tail {s : wseq α} {a} : a ∈ tail s → a ∈ s :=
id                                └──┘           └──┘      
src                               └──┘             └──┘       
typ                               └──┘           └──┘      
doc                               └──┘              └──┘
693  begin
st   └─────
694    intro h, have := h, cases h with n e, revert s, simp [stream.nth],
id                                                         └────────┘
src    └─────┘  └──────┘   └────┘ └───────┘  └──────┘  └────┘└────────┘
typ    └─────┘  └──────┘  └────┘└───────┘  └──────┘  └────┘└────────┘
doc    └─────┘  └──────┘   └────┘ └───────┘  └──────┘  └────┘          
txt    └─────┘  └──────┘   └────┘ └───────┘  └──────┘  └────┘          
par    └─────┘  └──────┘   └────┘ └───────┘  └──────┘  └────┘          
pid         └┘  └───┘└─┘         └───────┘        └┘                
st   ────────┘└─────────┘└────────────────┘└────────┘└─────────────────┘└─
695    induction n with n IH; intro s; apply s.cases_on _ (λx s, _) (λ s, _);
id                                          └────────┘
src    └────────┘ └────────┘  └─────┘  └────┘└────────┘└─┘  └──────┘  └────┘
typ    └────────┘└────────┘  └─────┘  └────┘└────────┘└─┘  └──────┘  └────┘
doc    └────────┘ └────────┘  └─────┘  └────┘          └─┘  └──────┘  └────┘
txt    └────────┘ └────────┘  └─────┘  └────┘          └─┘  └──────┘  └────┘
par    └────────┘ └────────┘  └─────┘  └────┘          └─┘  └──────┘  └────┘
pid              └───────┘       └┘                 └─┘  └──────┘  └────┘
st   ─────────────────────────────────────────────────────────────────────────
696      repeat{simp}; intros m e; injections,
src      └─────┘└──┘  └────────┘  └────────┘
typ      └─────┘└──┘  └────────┘  └────────┘
doc      └─────┘└──┘  └────────┘  └────────┘
txt      └─────┘└──┘  └────────┘  └────────┘
par      └─────┘└──┘  └────────┘  └────────┘
pid            └────┘        └──┘
st   ──────────┘└────┘└─────────────────────┘└─
697    { exact or.inr m },
id             └────┘ 
src      └────┘└────┘ 
typ      └────┘└────┘
doc      └────┘       
txt      └────┘       
par      └────┘       
pid                  
st   ───┘└─────────────┘└┘
698    { exact or.inr m },
id             └────┘ 
src      └────┘└────┘ 
typ      └────┘└────┘
doc      └────┘       
txt      └────┘       
par      └────┘       
pid                  
st   ───┘└─────────────┘└┘
699    { apply IH m, rw e, cases tail s, refl }
id             └┘              └──┘ 
src      └────┘     └─┘   └────┘└──┘   └───┘
typ      └────┘└┘  └─┘  └────┘└──┘  └───┘
doc      └────┘     └─┘   └────┘└──┘   └───┘
txt      └────┘     └─┘   └────┘       └───┘
par      └────┘     └─┘   └────┘       └───┘
pid                                     
st   ─────────────┘└────┘└────────────┘└─────┘└─
700  end
st   ──┘
701  
702  theorem mem_of_mem_dropn {s : wseq α} {a} : ∀ {n}, a ∈ drop s n → a ∈ s
id                                 └──┘                └──┘       
src                                └──┘                    └──┘         
typ                                └──┘                └──┘       
doc                                └──┘                     └──┘
703  | 0     h := h
id           
typ          
704  | (n+1) h := @mem_of_mem_dropn n (mem_of_mem_tail h)
id              └──────────────┘    └─────────────┘
src                                   └─────────────┘
typ             └──────────────┘    └─────────────┘
705  
706  theorem nth_mem {s : wseq α} {a n} : some a ∈ nth s n → a ∈ s :=
id                        └──┘           └──┘   └─┘       
src                       └──┘            └──┘    └─┘         
typ                       └──┘           └──┘   └─┘       
doc                       └──┘                     └─┘
707  begin
st   └─────
708    revert s, induction n with n IH; intros s h,
id                         
src    └──────┘  └────────┘ └────────┘  └────────┘
typ    └──────┘  └────────┘└────────┘  └────────┘
doc    └──────┘  └────────┘ └────────┘  └────────┘
txt    └──────┘  └────────┘ └────────┘  └────────┘
par    └──────┘  └────────┘ └────────┘  └────────┘
pid          └┘            └───────┘        └──┘
st   ─────────┘└─────────────────────────────────┘└─
709    { rcases exists_of_mem_map h with ⟨o, h1, h2⟩,
id              └───────────────┘ 
src      └─────┘└───────────────┘ └───────────────┘
typ      └─────┘└───────────────┘└───────────────┘
doc      └─────┘                  └───────────────┘
txt      └─────┘                  └───────────────┘
par      └─────┘                  └───────────────┘
pid                              └───────────────┘
st   ───┘└─────────────────────────────────────────┘└─
710      cases o with o; injection h2 with h',
id                                └┘
src      └────┘ └─────┘  └────────┘  └──────┘
typ      └────┘└─────┘  └────────┘└┘└──────┘
doc      └────┘ └─────┘  └────────┘  └──────┘
txt      └────┘ └─────┘  └────────┘  └──────┘
par      └────┘ └─────┘  └────────┘  └──────┘
pid            └─────┘             └──────┘
st   ───────────────────────────────────────┘└─
711      cases o with a' s',
id             
src      └────┘ └─────────┘
typ      └────┘└─────────┘
doc      └────┘ └─────────┘
txt      └────┘ └─────────┘
par      └────┘ └─────────┘
pid            └─────────┘
st   ─────────────────────┘└─
712      exact (eq_or_mem_iff_mem h1).2 (or.inl h'.symm) },
id              └───────────────┘ └┘     └────┘ └─────┘
src      └────┘ └───────────────┘  └──┘ └────┘└─────┘└┘
typ      └────┘ └───────────────┘└┘└──┘ └────┘└─────┘└┘
doc      └────┘                    └──┘              └┘
txt      └────┘                    └──┘              └┘
par      └────┘                    └──┘              └┘
pid                               └──┘              
st   ───────────────────────────────────────────────────┘└┘
713    { have := @IH (tail s), rw nth_tail at this,
id                └┘  └──┘       └──────┘
src      └──────┘    └──┘   └─┘└──────┘└──────┘
typ      └──────┘ └┘ └──┘  └─┘└──────┘└──────┘
doc      └──────┘    └──┘   └─┘        └──────┘
txt      └──────┘           └─┘        └──────┘
par      └──────┘           └─┘        └──────┘
pid      └───┘└─┘                     └──────┘
st   ───────────────────────┘└───────────────────┘└─
714      exact mem_of_mem_tail (this h) }
id             └─────────────┘  └──┘ 
src      └────┘└─────────────┘      └┘
typ      └────┘└─────────────┘ └──┘└┘
doc      └────┘                     └┘
txt      └────┘                     └┘
par      └────┘                     └┘
pid                                
st   ──────────────────────────────────┘└─
715  end
st   ──┘
716  
717  theorem exists_nth_of_mem {s : wseq α} {a} (h : a ∈ s) : ∃ n, some a ∈ nth s n :=
id                                  └──┘                    └──┘   └─┘  
src                                 └──┘                        └──┘    └─┘
typ                                 └──┘                    └──┘   └─┘  
doc                                 └──┘                                    └─┘
718  begin
st   └─────
719    apply mem_rec_on h,
id           └────────┘ 
src    └────┘└────────┘
typ    └────┘└────────┘
doc    └────┘          
txt    └────┘          
par    └────┘          
pid                   
st   ───────────────────┘└─
720    { intros a' s' h, cases h with h h,
id                             
src      └────────────┘  └────┘ └───────┘
typ      └────────────┘  └────┘└───────┘
doc      └────────────┘  └────┘ └───────┘
txt      └────────────┘  └────┘ └───────┘
par      └────────────┘  └────┘ └───────┘
pid            └──────┘        └───────┘
st   ───┘└────────────┘└────────────────┘└─
721      { existsi 0, simp [nth], rw h, apply ret_mem },
id                          └─┘              └─────┘
src        └───────┘  └────┘└─┘  └─┘   └────┘└─────┘
typ        └───────┘  └────┘└─┘  └─┘  └────┘└─────┘
doc        └───────┘  └────┘└─┘  └─┘   └────┘       
txt        └───────┘  └────┘     └─┘   └────┘       
par        └───────┘  └────┘     └─┘   └────┘       
pid                                           
st   ─────┘└───────┘└──────────┘└────┘└──────────────┘└┘
722      { cases h with n h, existsi n+1,
id                                  
src        └────┘ └───────┘  └──────┘ 
typ        └────┘└───────┘  └──────┘
doc        └────┘ └───────┘  └──────┘  
txt        └────┘ └───────┘  └──────┘  
par        └────┘ └───────┘  └──────┘  
pid              └───────┘           
st   ─────────────────────┘└───────────┘└─
723        simp [nth], exact h } },
id               └─┘         
src        └────┘└─┘  └────┘ 
typ        └────┘└─┘  └────┘
doc        └────┘└─┘  └────┘ 
txt        └────┘     └────┘ 
par        └────┘     └────┘ 
pid                       
st   ───────────────┘└────────┘└──┘
724    { intros s' h, cases h with n h,
id                          
src      └─────────┘  └────┘ └───────┘
typ      └─────────┘  └────┘└───────┘
doc      └─────────┘  └────┘ └───────┘
txt      └─────────┘  └────┘ └───────┘
par      └─────────┘  └────┘ └───────┘
pid            └───┘        └───────┘
st   ──────────────┘└────────────────┘└─
725      existsi n, simp [nth], apply think_mem h }
id                       └─┘         └───────┘ 
src      └──────┘   └────┘└─┘  └────┘└───────┘ 
typ      └──────┘  └────┘└─┘  └────┘└───────┘
doc      └──────┘   └────┘└─┘  └────┘          
txt      └──────┘   └────┘     └────┘          
par      └──────┘   └────┘     └────┘          
pid                                        
st   ────────────┘└──────────┘└──────────────────┘└─
726  end
st   ──┘
727  
728  theorem exists_dropn_of_mem {s : wseq α} {a} (h : a ∈ s) :
id                                    └──┘              
src                                   └──┘               
typ                                   └──┘              
doc                                   └──┘
729    ∃ n s', some (a, s') ∈ destruct (drop s n) :=
id       └┘ └──┘   └┘   └──────┘  └──┘  
src          └──┘         └──────┘  └──┘
typ      └┘ └──┘   └┘   └──────┘  └──┘  
doc                           └──────┘  └──┘
730  let ⟨n, h⟩ := exists_nth_of_mem h in ⟨n, begin
id   └─┘          └───────────────┘ 
src                └───────────────┘
typ  └─┘          └───────────────┘ 
st                                            └─────
731    cases (head_terminates_iff _).1 ⟨_, h⟩ with o om,
id            └─────────────────┘          
src    └────┘ └─────────────────┘└────┘ └─┘ └─────────┘
typ    └────┘ └─────────────────┘└────┘ └─┘└─────────┘
doc    └────┘                    └────┘ └─┘ └─────────┘
txt    └────┘                    └────┘ └─┘ └─────────┘
par    └────┘                    └────┘ └─┘ └─────────┘
pid                             └────┘ └─┘ └────────┘
st   ─────────────────────────────────────────────────┘└─
732    have := mem_unique (mem_map _ om) h,
id             └────────┘  └─────┘   └┘  
src    └──────┘└────────┘ └─────┘└─┘  └┘
typ    └──────┘└────────┘ └─────┘└─┘└┘└┘
doc    └──────┘                  └─┘  └┘
txt    └──────┘                  └─┘  └┘
par    └──────┘                  └─┘  └┘
pid    └───┘└─┘                  └─┘  └┘
st   ────────────────────────────────────┘└─
733    cases o with o; injection this with i,
id                              └──┘
src    └────┘ └─────┘  └────────┘    └─────┘
typ    └────┘└─────┘  └────────┘└──┘└─────┘
doc    └────┘ └─────┘  └────────┘    └─────┘
txt    └────┘ └─────┘  └────────┘    └─────┘
par    └────┘ └─────┘  └────────┘    └─────┘
pid          └─────┘               └─────┘
st   ──────────────────────────────────────┘└─
734    cases o with a' s', dsimp at i,
id           
src    └────┘ └─────────┘  └────────┘
typ    └────┘└─────────┘  └────────┘
doc    └────┘ └─────────┘  └────────┘
txt    └────┘ └─────────┘  └────────┘
par    └────┘ └─────────┘  └────────┘
pid          └─────────┘       └──┘
st   ───────────────────┘└──────────┘└─
735    rw i at om, exact ⟨_, om⟩
id                          └┘
src    └─┘ └────┘  └────┘ └─┘  └┘
typ    └─┘└────┘  └────┘ └─┘└┘└┘
doc    └─┘ └────┘  └────┘ └─┘  └┘
txt    └─┘ └────┘  └────┘ └─┘  └┘
par    └─┘ └────┘  └────┘ └─┘  └┘
pid       └────┘        └─┘  
st   ───────────┘└──────────────┘
736  end⟩
st   └─┘
737  
738  theorem lift_rel_dropn_destruct {R : α → β → Prop} {s t} (H : lift_rel R s t) :
id                                                               └──────┘   
src                                                                └──────┘
typ                                                              └──────┘   
doc                                                                └──────┘
739    ∀ n, computation.lift_rel (lift_rel_o R (lift_rel R))
id         └──────────────────┘  └────────┘   └──────┘ 
src         └──────────────────┘  └────────┘    └──────┘
typ        └──────────────────┘  └────────┘   └──────┘ 
doc         └──────────────────┘                └──────┘
740      (destruct (drop s n)) (destruct (drop t n))
id        └──────┘  └──┘      └──────┘  └──┘  
src       └──────┘  └──┘        └──────┘  └──┘
typ       └──────┘  └──┘      └──────┘  └──┘  
doc       └──────┘  └──┘        └──────┘  └──┘
741  | 0     := lift_rel_destruct H
id              └───────────────┘ 
src             └───────────────┘
typ             └───────────────┘ 
742  | (n+1) := begin
id       
src      
typ      
st              └─────
743    simp [destruct_tail],
id           └───────────┘
src    └────┘└───────────┘
typ    └────┘└───────────┘
doc    └────┘             
txt    └────┘             
par    └────┘             
pid                     
st   ─────────────────────┘└─
744    apply lift_rel_bind,
id           └───────────┘
src    └────┘└───────────┘
typ    └────┘└───────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ────────────────────┘└─
745    apply lift_rel_dropn_destruct n,
id           └─────────────────────┘ 
src    └────┘                       
typ    └────┘└─────────────────────┘
doc    └────┘                       
txt    └────┘                       
par    └────┘                       
pid                                
st   ────────────────────────────────┘└─
746    exact λ a b o, match a, b, o with
src    └────┘ └──────┘      └┘ └┘ └─────
typ    └────┘ └──────┘      └┘ └┘ └─────
doc    └────┘ └──────┘      └┘ └┘ └─────
txt    └────┘ └──────┘      └┘ └┘ └─────
par    └────┘ └──────┘      └┘ └┘ └─────
pid          └──────┘      └┘ └┘ └─────
st   ────────────────────────────────────
747    | none,       none,         _        := by simp
src  ───┘    └──────┘    └────────────────────┘  └────
typ  ───┘    └──────┘    └────────────────────┘  └────
doc  ───┘    └──────┘    └────────────────────┘  └────
txt  ───┘    └──────┘    └────────────────────┘  └────
par  ───┘    └──────┘    └────────────────────┘  └────
pid  ───┘    └──────┘    └────────────────────┘  └─────
st   ───────────────────────────────────────────┘└─────
748    | some (a, s), some (b, t), ⟨h1, h2⟩ := by simp [tail.aux]; apply lift_rel_destruct h2
id                   └──┘                              └──────┘         └───────────────┘ └┘
src  ─┘└┘     └┘ └─┘└──┘  └┘ └─┘   └┘  └───┘  └────┘└──────┘└┘└────┘└───────────────┘  
typ  ─┘└┘     └┘ └─┘└──┘  └┘ └─┘   └┘  └───┘  └────┘└──────┘└──────┘└───────────────┘└┘
doc  ─┘└┘      └┘ └─┘      └┘ └─┘   └┘  └───┘  └────┘        └┘└────┘                   
txt  ─┘└┘      └┘ └─┘      └┘ └─┘   └┘  └───┘  └────┘        └┘└────┘                   
par  ─┘└┘      └┘ └─┘      └┘ └─┘   └┘  └───┘  └────┘        └──────┘                   
pid  ───┘      └┘ └─┘      └┘ └─┘   └┘  └───┘  └─────┘        └───────┘                   
st   ─┘└────────────────────────────────────────┘└────────────────────────────────────────────
749    end
src  ─┘└──┘
typ  ─────┘
doc  ─┘└──┘
txt  ─┘└──┘
par  ─────┘
pid  ────┘
st   ─┘└──┘
750  end
st   └─┘
751  
752  theorem exists_of_lift_rel_left {R : α → β → Prop} {s t}
id                                           
typ                                          
753    (H : lift_rel R s t) {a} (h : a ∈ s) : ∃ {b}, b ∈ t ∧ R a b :=
id          └──────┘                              
src         └──────┘                                   
typ         └──────┘                              
doc         └──────┘
754  let ⟨n, h⟩ := exists_nth_of_mem h,
id   └─┘         └───────────────┘ 
src                └───────────────┘
typ  └─┘         └───────────────┘ 
755      ⟨some (._, s'), sd, rfl⟩ := exists_of_mem_map h,
id        └──┘          └┘  └─┘     └───────────────┘
src       └──┘              └─┘     └───────────────┘
typ       └──┘          └┘  └─┘     └───────────────┘
756      ⟨some (b, t'), td, ⟨ab, _⟩⟩ := (lift_rel_dropn_destruct H n).left sd in
id        └──┘        └┘   └┘          └─────────────────────┘    └──┘
src       └──┘                          └─────────────────────┘     └──┘
typ       └──┘        └┘   └┘          └─────────────────────┘    └──┘
757  ⟨b, nth_mem (mem_map ((<$>) prod.fst.{v v}) td), ab⟩
id       └─────┘  └─────┘       └──────┘
src      └─────┘  └─────┘       └──────┘
typ      └─────┘  └─────┘       └──────┘
758  
759  theorem exists_of_lift_rel_right {R : α → β → Prop} {s t}
id                                            
typ                                           
760    (H : lift_rel R s t) {b} (h : b ∈ t) : ∃ {a}, a ∈ s ∧ R a b :=
id          └──────┘                              
src         └──────┘                                   
typ         └──────┘                              
doc         └──────┘
761  by rw ←lift_rel.swap at H; exact exists_of_lift_rel_left H h
id          └───────────┘             └─────────────────────┘  
src     └──┘└───────────┘└───┘  └────┘└─────────────────────┘  
typ     └──┘└───────────┘└───┘  └────┘└─────────────────────┘
doc     └──┘             └───┘  └────┘                         
txt     └──┘             └───┘  └────┘                         
par     └──┘             └───┘  └────┘                         
pid       └┘             └───┘                                
st     └──────────────────────────────────────────────────────────
762  
src  
typ  
doc  
txt  
par  
pid  
st   
763  theorem head_terminates_of_mem {s : wseq α} {a} (h : a ∈ s) : terminates (head s) :=
id                                       └──┘                  └────────┘  └──┘ 
src                                      └──┘                     └────────┘  └──┘
typ                                      └──┘                  └────────┘  └──┘ 
doc                                      └──┘                      └────────┘  └──┘
764  let ⟨n, h⟩ := exists_nth_of_mem h in head_terminates_of_nth_terminates ⟨_, h⟩
id   └─┘          └───────────────┘     └───────────────────────────────┘
src                └───────────────┘      └───────────────────────────────┘
typ  └─┘          └───────────────┘     └───────────────────────────────┘
765  
766  theorem of_mem_append {s₁ s₂ : wseq α} {a : α} : a ∈ append s₁ s₂ → a ∈ s₁ ∨ a ∈ s₂ :=
id                                  └──┘              └────┘ └┘ └┘     └┘    └┘
src                                 └──┘                 └────┘                  
typ                                 └──┘              └────┘ └┘ └┘     └┘    └┘
doc                                 └──┘                  └────┘
767  seq.of_mem_append
id   └───────────────┘
src  └───────────────┘
typ  └───────────────┘
768  
769  theorem mem_append_left {s₁ s₂ : wseq α} {a : α} : a ∈ s₁ → a ∈ append s₁ s₂ :=
id                                    └──┘              └┘     └────┘ └┘ └┘
src                                   └──┘                         └────┘
typ                                   └──┘              └┘     └────┘ └┘ └┘
doc                                   └──┘                           └────┘
770  seq.mem_append_left
id   └─────────────────┘
src  └─────────────────┘
typ  └─────────────────┘
771  
772  theorem exists_of_mem_map {f} {b : β} : ∀ {s : wseq α}, b ∈ map f s → ∃ a, a ∈ s ∧ f a = b
id                                                └──┘      └─┘              
src                                                 └──┘        └─┘                    
typ                                               └──┘      └─┘              
doc                                                 └──┘         └─┘
773  | ⟨g, al⟩ h := let ⟨o, om, oe⟩ := seq.exists_of_mem_map h in
id                 └─┘                └───────────────────┘
src                                    └───────────────────┘
typ                └─┘                └───────────────────┘
774    by cases o with a; injection oe with h'; exact ⟨a, om, h'⟩
id                                 └┘                   └┘  └┘
src       └────┘ └─────┘  └────────┘  └──────┘  └────┘  └┘  └┘  └─
typ       └────┘└─────┘  └────────┘└┘└──────┘  └────┘ └┘└┘└┘└┘└─
doc       └────┘ └─────┘  └────────┘  └──────┘  └────┘  └┘  └┘  └─
txt       └────┘ └─────┘  └────────┘  └──────┘  └────┘  └┘  └┘  └─
par       └────┘ └─────┘  └────────┘  └──────┘  └────┘  └┘  └┘  └─
pid             └─────┘             └──────┘         └┘  └┘  
st       └────────────────────────────────────────────────────────
775  
src  
typ  
doc  
txt  
par  
pid  
st   
776  @[simp] theorem lift_rel_nil (R : α → β → Prop) : lift_rel R nil nil :=
id                                                   └──────┘  └─┘ └─┘
src                                                    └──────┘   └─┘ └─┘
typ                                                  └──────┘  └─┘ └─┘
doc    └──┘                                            └──────┘   └─┘ └─┘
777  by rw [lift_rel_destruct_iff]; simp
id          └───────────────────┘
src     └──┘└───────────────────┘  └────
typ     └──┘└───────────────────┘  └────
doc     └──┘                       └────
txt     └──┘                       └────
par     └──┘                       └────
pid       └┘                           
st     └────────────────────────┘└──────
778  
src  
typ  
doc  
txt  
par  
pid  
st   
779  @[simp] theorem lift_rel_cons (R : α → β → Prop) (a b s t) :
id                                         
typ                                        
doc    └──┘
780    lift_rel R (cons a s) (cons b t) ↔ R a b ∧ lift_rel R s t :=
id     └──────┘   └──┘     └──┘         └──────┘   
src    └──────┘    └──┘       └──┘              └──────┘
typ    └──────┘   └──┘     └──┘         └──────┘   
doc    └──────┘    └──┘       └──┘                └──────┘
781  by rw [lift_rel_destruct_iff]; simp
id          └───────────────────┘
src     └──┘└───────────────────┘  └────
typ     └──┘└───────────────────┘  └────
doc     └──┘                       └────
txt     └──┘                       └────
par     └──┘                       └────
pid       └┘                           
st     └────────────────────────┘└──────
782  
src  
typ  
doc  
txt  
par  
pid  
st   
783  @[simp] theorem lift_rel_think_left (R : α → β → Prop) (s t) :
id                                               
typ                                              
doc    └──┘
784    lift_rel R (think s) t ↔ lift_rel R s t :=
id     └──────┘   └───┘     └──────┘   
src    └──────┘    └───┘       └──────┘
typ    └──────┘   └───┘     └──────┘   
doc    └──────┘    └───┘        └──────┘
785  by rw [lift_rel_destruct_iff, lift_rel_destruct_iff]; simp
id          └───────────────────┘  └───────────────────┘
src     └──┘└───────────────────┘└┘└───────────────────┘  └────
typ     └──┘└───────────────────┘└┘└───────────────────┘  └────
doc     └──┘                     └┘                       └────
txt     └──┘                     └┘                       └────
par     └──┘                     └┘                       └────
pid       └┘                     └┘                           
st     └────────────────────────┘└─────────────────────┘└──────
786  
src  
typ  
doc  
txt  
par  
pid  
st   
787  @[simp] theorem lift_rel_think_right (R : α → β → Prop) (s t) :
id                                                
typ                                               
doc    └──┘
788    lift_rel R s (think t) ↔ lift_rel R s t :=
id     └──────┘    └───┘    └──────┘   
src    └──────┘      └───┘     └──────┘
typ    └──────┘    └───┘    └──────┘   
doc    └──────┘      └───┘      └──────┘
789  by rw [lift_rel_destruct_iff, lift_rel_destruct_iff]; simp
id          └───────────────────┘  └───────────────────┘
src     └──┘└───────────────────┘└┘└───────────────────┘  └────
typ     └──┘└───────────────────┘└┘└───────────────────┘  └────
doc     └──┘                     └┘                       └────
txt     └──┘                     └┘                       └────
par     └──┘                     └┘                       └────
pid       └┘                     └┘                           
st     └────────────────────────┘└─────────────────────┘└──────
790  
src  
typ  
doc  
txt  
par  
pid  
st   
791  theorem cons_congr {s t : wseq α} (a : α) (h : s ~ t) : cons a s ~ cons a t :=
id                             └──┘                     └──┘    └──┘  
src                            └──┘                         └──┘      └──┘
typ                            └──┘                     └──┘    └──┘  
doc                            └──┘                         └──┘      └──┘
792  by unfold equiv; simp; exact h
id                                
src     └──────────┘  └──┘  └────┘ 
typ     └──────────┘  └──┘  └────┘
doc     └──────────┘  └──┘  └────┘ 
txt     └──────────┘  └──┘  └────┘ 
par     └──────────┘  └──┘  └────┘ 
pid           └────┘              
st     └────────────────────────────
793  
src  
typ  
doc  
txt  
par  
pid  
st   
794  theorem think_equiv (s : wseq α) : think s ~ s :=
id                            └──┘     └───┘   
src                           └──┘      └───┘   
typ                           └──┘     └───┘   
doc                           └──┘      └───┘   
795  by unfold equiv; simp; apply equiv.refl
id                                └────────┘
src     └──────────┘  └──┘  └────┘└────────┘
typ     └──────────┘  └──┘  └────┘└────────┘
doc     └──────────┘  └──┘  └────┘          
txt     └──────────┘  └──┘  └────┘          
par     └──────────┘  └──┘  └────┘          
pid           └────┘                       
st     └─────────────────────────────────────
796  
src  
typ  
doc  
txt  
par  
pid  
st   
797  theorem think_congr {s t : wseq α} (a : α) (h : s ~ t) : think s ~ think t :=
id                              └──┘                     └───┘   └───┘ 
src                             └──┘                         └───┘    └───┘
typ                             └──┘                     └───┘   └───┘ 
doc                             └──┘                         └───┘    └───┘
798  by unfold equiv; simp; exact h
id                                
src     └──────────┘  └──┘  └────┘ 
typ     └──────────┘  └──┘  └────┘
doc     └──────────┘  └──┘  └────┘ 
txt     └──────────┘  └──┘  └────┘ 
par     └──────────┘  └──┘  └────┘ 
pid           └────┘              
st     └────────────────────────────
799  
src  
typ  
doc  
txt  
par  
pid  
st   
800  theorem head_congr : ∀ {s t : wseq α}, s ~ t → head s ~ head t :=
id                                 └──┘         └──┘   └──┘ 
src                                └──┘            └──┘    └──┘
typ                                └──┘         └──┘   └──┘ 
doc                                └──┘            └──┘    └──┘
801  suffices ∀ {s t : wseq α}, s ~ t → ∀ {o}, o ∈ head s → o ∈ head t, from
id                     └──┘                 └──┘      └──┘ 
src                    └──┘                      └──┘        └──┘
typ                    └──┘                 └──┘      └──┘ 
doc                    └──┘                       └──┘         └──┘
802  λ s t h o, ⟨this h, this h.symm⟩,
id           └──┘   └──┘ └───┘
src                            └───┘
typ          └──┘   └──┘ └───┘
803  begin
st   └─────
804    intros s t h o ho,
src    └───────────────┘
typ    └───────────────┘
doc    └───────────────┘
txt    └───────────────┘
par    └───────────────┘
pid          └─────────┘
st   ──────────────────┘└─
805    rcases @computation.exists_of_mem_map _ _ _ _ (destruct s) ho with ⟨ds, dsm, dse⟩,
id             └───────────────────────────┘          └──────┘   └┘
src    └─────┘ └───────────────────────────┘└───────┘ └──────┘ └┘  └──────────────────┘
typ    └─────┘ └───────────────────────────┘└───────┘ └──────┘└┘└┘└──────────────────┘
doc    └─────┘                              └───────┘ └──────┘ └┘  └──────────────────┘
txt    └─────┘                              └───────┘          └┘  └──────────────────┘
par    └─────┘                              └───────┘          └┘  └──────────────────┘
pid                                        └───────┘          └┘  └──────────────────┘
st   ──────────────────────────────────────────────────────────────────────────────────┘└─
806    rw ←dse,
id         └─┘
src    └──┘
typ    └──┘└─┘
doc    └──┘
txt    └──┘
par    └──┘
pid      └┘
st   ────────┘└─
807    cases destruct_congr h with l r,
id           └────────────┘ 
src    └────┘└────────────┘ └───────┘
typ    └────┘└────────────┘└───────┘
doc    └────┘               └───────┘
txt    └────┘               └───────┘
par    └────┘               └───────┘
pid                        └───────┘
st   ────────────────────────────────┘└─
808    rcases l dsm with ⟨dt, dtm, dst⟩,
id             └─┘
src    └─────┘    └──────────────────┘
typ    └─────┘└─┘└──────────────────┘
doc    └─────┘    └──────────────────┘
txt    └─────┘    └──────────────────┘
par    └─────┘    └──────────────────┘
pid              └──────────────────┘
st   ─────────────────────────────────┘└─
809    cases ds with a; cases dt with b,
id           └┘               └┘
src    └────┘  └─────┘  └────┘  └─────┘
typ    └────┘└┘└─────┘  └────┘└┘└─────┘
doc    └────┘  └─────┘  └────┘  └─────┘
txt    └────┘  └─────┘  └────┘  └─────┘
par    └────┘  └─────┘  └────┘  └─────┘
pid           └─────┘         └─────┘
st   ─────────────────────────────────┘└─
810    { apply mem_map _ dtm },
id             └─────┘   └─┘
src      └────┘└─────┘└─┘   
typ      └────┘└─────┘└─┘└─┘
doc      └────┘       └─┘   
txt      └────┘       └─┘   
par      └────┘       └─┘   
pid                  └─┘   
st   ───┘└──────────────────┘└┘
811    { cases b, cases dst },
id                     └─┘
src      └────┘   └────┘   
typ      └────┘  └────┘└─┘
doc      └────┘   └────┘   
txt      └────┘   └────┘   
par      └────┘   └────┘   
pid                      
st   ───┘└─────┘└──────────┘└┘
812    { cases a, cases dst },
id                     └─┘
src      └────┘   └────┘   
typ      └────┘  └────┘└─┘
doc      └────┘   └────┘   
txt      └────┘   └────┘   
par      └────┘   └────┘   
pid                      
st   ───┘└─────┘└──────────┘└┘
813    { cases a with a s', cases b with b t', rw dst.left,
id                               
src      └────┘ └────────┘  └────┘ └────────┘  └─┘
typ      └────┘└────────┘  └────┘└────────┘  └─┘└──────┘
doc      └────┘ └────────┘  └────┘ └────────┘  └─┘
txt      └────┘ └────────┘  └────┘ └────────┘  └─┘
par      └────┘ └────────┘  └────┘ └────────┘  └─┘
pid            └────────┘        └────────┘    
st   ────────────────────┘└─────────────────┘└───────────┘└─
814      exact @mem_map _ _ (@functor.map _ _ (α × wseq α) _ prod.fst)
id              └─────┘       └─────────┘         └──┘     └──────┘
src      └────┘ └─────┘└───┘  └─────────┘└───┘  └──┘ └──┘└──────┘└─
typ      └────┘ └─────┘└───┘  └─────────┘└───┘  └──┘└──┘└──────┘└─
doc      └────┘        └───┘             └───┘   └──┘ └──┘        └─
txt      └────┘        └───┘             └───┘        └──┘        └─
par      └────┘        └───┘             └───┘        └──┘        └─
pid                   └───┘             └───┘        └──┘        └─
st   ──────────────────────────────────────────────────────────────────
815        _ (destruct t) dtm }
id            └──────┘   └─┘
src  ───────┘ └──────┘ └┘   
typ  ───────┘ └──────┘└┘└─┘
doc  ───────┘ └──────┘ └┘   
txt  ───────┘          └┘   
par  ───────┘          └┘   
pid  ───────┘          └┘   
st   ────────────────────────┘└─
816  end
st   ──┘
817  
818  theorem flatten_equiv {c : computation (wseq α)} {s} (h : s ∈ c) : flatten c ~ s :=
id                              └─────────┘  └──┘                   └─────┘   
src                             └─────────┘  └──┘                      └─────┘   
typ                             └─────────┘  └──┘                   └─────┘   
doc                             └─────────┘  └──┘                       └─────┘   
819  begin
st   └─────
820    apply computation.mem_rec_on h, { simp },
id           └────────────────────┘ 
src    └────┘└────────────────────┘     └───┘
typ    └────┘└────────────────────┘    └───┘
doc    └────┘                           └───┘
txt    └────┘                           └───┘
par    └────┘                           └───┘
pid                                        
st   ───────────────────────────────┘└──┘└───┘└┘
821    { intro s', apply equiv.trans, simp [think_equiv] }
id                       └─────────┘        └─────────┘
src      └──────┘  └────┘└─────────┘  └────┘└─────────┘└┘
typ      └──────┘  └────┘└─────────┘  └────┘└─────────┘└┘
doc      └──────┘  └────┘             └────┘           └┘
txt      └──────┘  └────┘             └────┘           └┘
par      └──────┘  └────┘             └────┘           └┘
pid           └─┘                                   
st   ───────────┘└─────────────────┘└───────────────────┘└─
822  end
st   ──┘
823  
824  theorem lift_rel_flatten {R : α → β → Prop} {c1 : computation (wseq α)} {c2 : computation (wseq β)}
id                                                   └─────────┘  └──┘          └─────────┘  └──┘ 
src                                                    └─────────┘  └──┘           └─────────┘  └──┘
typ                                                  └─────────┘  └──┘          └─────────┘  └──┘ 
doc                                                    └─────────┘  └──┘           └─────────┘  └──┘
825    (h : c1.lift_rel (lift_rel R) c2) : lift_rel R (flatten c1) (flatten c2) :=
id          └┘└───────┘  └──────┘   └┘    └──────┘   └─────┘ └┘   └─────┘ └┘
src           └───────┘  └──────┘          └──────┘    └─────┘      └─────┘
typ         └┘└───────┘  └──────┘   └┘    └──────┘   └─────┘ └┘   └─────┘ └┘
doc           └───────┘  └──────┘          └──────┘    └─────┘      └─────┘
826  let S := λ s t,
id              
typ             
827    ∃ c1 c2, s = flatten c1 ∧ t = flatten c2 ∧ computation.lift_rel (lift_rel R) c1 c2 in
id      └┘ └┘   └─────┘ └┘    └─────┘ └┘  └──────────────────┘  └──────┘   └┘ └┘
src              └─────┘        └─────┘     └──────────────────┘  └──────┘
typ     └┘ └┘   └─────┘ └┘    └─────┘ └┘  └──────────────────┘  └──────┘   └┘ └┘
doc                 └─────┘          └─────┘      └──────────────────┘  └──────┘
828  ⟨S, ⟨c1, c2, rfl, rfl, h⟩, λ s t h,
id       └┘  └┘  └─┘  └─┘         
src               └─┘  └─┘
typ      └┘  └┘  └─┘  └─┘         
829    match s, t, h with ._, ._, ⟨c1, c2, rfl, rfl, h⟩ := begin
id                                           └─┘
src                                             └─┘
typ                                          └─┘
st                                                         └─────
830      simp, apply lift_rel_bind _ _ h,
id                   └───────────┘     
src      └──┘  └────┘└───────────┘└───┘
typ      └──┘  └────┘└───────────┘└───┘
doc      └──┘  └────┘             └───┘
txt      └──┘  └────┘             └───┘
par      └──┘  └────┘             └───┘
pid                              └───┘
st   ───────┘└─────────────────────────┘└─
831      intros a b ab, apply computation.lift_rel.imp _ _ _ (lift_rel_destruct ab),
id                            └──────────────────────┘        └───────────────┘ └┘
src      └───────────┘  └────┘└──────────────────────┘└─────┘ └───────────────┘  
typ      └───────────┘  └────┘└──────────────────────┘└─────┘ └───────────────┘└┘
doc      └───────────┘  └────┘                        └─────┘                    
txt      └───────────┘  └────┘                        └─────┘                    
par      └───────────┘  └────┘                        └─────┘                    
pid            └─────┘                               └─────┘                    
st   ────────────────┘└───────────────────────────────────────────────────────────┘└─
832      intros a b, apply lift_rel_o.imp_right,
id                         └──────────────────┘
src      └────────┘  └────┘└──────────────────┘
typ      └────────┘  └────┘└──────────────────┘
doc      └────────┘  └────┘
txt      └────────┘  └────┘
par      └────────┘  └────┘
pid            └──┘       
st   ─────────────┘└──────────────────────────┘└─
833      intros s t h, refine ⟨return s, return t, _, _, _⟩; simp [h]
id                             └────┘                            
src      └──────────┘  └─────┘ └────┘ └┘       └────────┘  └────┘ └─
typ      └──────────┘  └─────┘ └────┘└┘      └────────┘  └────┘└─
doc      └──────────┘  └─────┘ └────┘ └┘       └────────┘  └────┘ └─
txt      └──────────┘  └─────┘        └┘       └────────┘  └────┘ └─
par      └──────────┘  └─────┘        └┘       └────────┘  └────┘ └─
pid            └────┘                └┘       └────────┘       
st   ───────────────┘└────────────────────────────────────────────────
834    end end⟩
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
835  
836  theorem flatten_congr {c1 c2 : computation (wseq α)} :
id                                  └─────────┘  └──┘ 
src                                 └─────────┘  └──┘
typ                                 └─────────┘  └──┘ 
doc                                 └─────────┘  └──┘
837    computation.lift_rel equiv c1 c2 → flatten c1 ~ flatten c2 := lift_rel_flatten
id     └──────────────────┘ └───┘ └┘ └┘   └─────┘ └┘  └─────┘ └┘    └──────────────┘
src    └──────────────────┘ └───┘         └─────┘     └─────┘       └──────────────┘
typ    └──────────────────┘ └───┘ └┘ └┘   └─────┘ └┘  └─────┘ └┘    └──────────────┘
doc    └──────────────────┘ └───┘         └─────┘     └─────┘
838  
839  theorem tail_congr {s t : wseq α} (h : s ~ t) : tail s ~ tail t :=
id                             └──┘              └──┘   └──┘ 
src                            └──┘                 └──┘    └──┘
typ                            └──┘              └──┘   └──┘ 
doc                            └──┘                 └──┘    └──┘
840  begin
st   └─────
841    apply flatten_congr,
id           └───────────┘
src    └────┘└───────────┘
typ    └────┘└───────────┘
doc    └────┘
txt    └────┘
par    └────┘
pid         
st   ────────────────────┘└─
842    unfold functor.map, rw [←bind_ret, ←bind_ret],
id                              └──────┘   └──────┘
src    └────────────────┘  └───┘└──────┘└─┘└──────┘
typ    └────────────────┘  └───┘└──────┘└─┘└──────┘
doc    └────────────────┘  └───┘        └─┘        
txt    └────────────────┘  └───┘        └─┘        
par    └────────────────┘  └───┘        └─┘        
pid          └──────────┘    └─┘        └─┘        
st   ───────────────────┘└─────────────┘└─────────┘└──
843    apply lift_rel_bind _ _ (destruct_congr h),
id           └───────────┘      └────────────┘ 
src    └────┘└───────────┘└───┘ └────────────┘ 
typ    └────┘└───────────┘└───┘ └────────────┘
doc    └────┘             └───┘                
txt    └────┘             └───┘                
par    └────┘             └───┘                
pid                      └───┘                
st   ───────────────────────────────────────────┘└─
844    intros a b h, simp,
src    └──────────┘  └──┘
typ    └──────────┘  └──┘
doc    └──────────┘  └──┘
txt    └──────────┘  └──┘
par    └──────────┘  └──┘
pid          └────┘
st   ─────────────┘└────┘└─
845    cases a with a; cases b with b,
id                          
src    └────┘ └─────┘  └────┘ └─────┘
typ    └────┘└─────┘  └────┘└─────┘
doc    └────┘ └─────┘  └────┘ └─────┘
txt    └────┘ └─────┘  └────┘ └─────┘
par    └────┘ └─────┘  └────┘ └─────┘
pid          └─────┘        └─────┘
st   ───────────────────────────────┘└─
846    { trivial },
src      └──────┘
typ      └──────┘
doc      └──────┘
txt      └──────┘
par      └──────┘
pid             
st   ───┘└──────┘└┘
847    { cases h },
id             
src      └────┘ 
typ      └────┘
doc      └────┘ 
txt      └────┘ 
par      └────┘ 
pid            
st   ───┘└──────┘└┘
848    { cases a, cases h },
id                     
src      └────┘   └────┘ 
typ      └────┘  └────┘
doc      └────┘   └────┘ 
txt      └────┘   └────┘ 
par      └────┘   └────┘ 
pid                    
st   ───┘└─────┘└────────┘└┘
849    { cases a with a s', cases b with b t', exact h.right }
id                                                 └─────┘
src      └────┘ └────────┘  └────┘ └────────┘  └────┘└─────┘
typ      └────┘└────────┘  └────┘└────────┘  └────┘└─────┘
doc      └────┘ └────────┘  └────┘ └────────┘  └────┘       
txt      └────┘ └────────┘  └────┘ └────────┘  └────┘       
par      └────┘ └────────┘  └────┘ └────────┘  └────┘       
pid            └────────┘        └────────┘              
st   ────────────────────┘└─────────────────┘└──────────────┘└─
850  end
st   ──┘
851  
852  theorem dropn_congr {s t : wseq α} (h : s ~ t) (n) : drop s n ~ drop t n :=
id                              └──┘                  └──┘    └──┘  
src                             └──┘                     └──┘      └──┘
typ                             └──┘                  └──┘    └──┘  
doc                             └──┘                     └──┘      └──┘
853  by induction n; simp [*, tail_congr]
id                           └────────┘
src     └────────┘   └───────┘└────────┘└─
typ     └────────┘  └───────┘└────────┘└─
doc     └────────┘   └───────┘          └─
txt     └────────┘   └───────┘          └─
par     └────────┘   └───────┘          └─
pid                     └──┘          
st     └──────────────────────────────────
854  
src  
typ  
doc  
txt  
par  
pid  
st   
855  theorem nth_congr {s t : wseq α} (h : s ~ t) (n) : nth s n ~ nth t n :=
id                            └──┘                  └─┘    └─┘  
src                           └──┘                     └─┘      └─┘
typ                           └──┘                  └─┘    └─┘  
doc                           └──┘                     └─┘      └─┘
856  head_congr (dropn_congr h _)
id   └────────┘  └─────────┘ 
src  └────────┘  └─────────┘
typ  └────────┘  └─────────┘ 
857  
858  theorem mem_congr {s t : wseq α} (h : s ~ t) (a) : a ∈ s ↔ a ∈ t :=
id                            └──┘                        
src                           └──┘                             
typ                           └──┘                        
doc                           └──┘           
859  suffices ∀ {s t : wseq α}, s ~ t → a ∈ s → a ∈ t, from ⟨this h, this h.symm⟩,
id                     └──┘                        └──┘   └──┘ └───┘
src                    └──┘                                             └───┘
typ                    └──┘                        └──┘   └──┘ └───┘
doc                    └──┘       
860  λ s t h as, let ⟨n, hn⟩ := exists_nth_of_mem as in
id        └┘  └─┘     └┘     └───────────────┘ └┘
src                             └───────────────┘
typ       └┘  └─┘     └┘     └───────────────┘ └┘
861  nth_mem ((nth_congr h _ _).1 hn)
id   └─────┘   └───────┘      
src  └─────┘   └───────┘       
typ  └─────┘   └───────┘      
862  
863  theorem productive_congr {s t : wseq α} (h : s ~ t) : productive s ↔ productive t :=
id                                   └──┘              └────────┘   └────────┘ 
src                                  └──┘                 └────────┘    └────────┘
typ                                  └──┘              └────────┘   └────────┘ 
doc                                  └──┘                 └────────┘     └────────┘
864  forall_congr $ λn, terminates_congr $ nth_congr h _
id   └──────────┘      └──────────────┘   └───────┘ 
src  └──────────┘       └──────────────┘   └───────┘
typ  └──────────┘      └──────────────┘   └───────┘ 
865  
866  theorem equiv.ext {s t : wseq α} (h : ∀ n, nth s n ~ nth t n) : s ~ t :=
id                            └──┘            └─┘    └─┘        
src                           └──┘              └─┘      └─┘          
typ                           └──┘            └─┘    └─┘        
doc                           └──┘              └─┘      └─┘          
867  ⟨λ s t, ∀ n, nth s n ~ nth t n, h, λs t h, begin
id             └─┘    └─┘         
src               └─┘      └─┘
typ            └─┘    └─┘         
doc               └─┘      └─┘
st                                              └─────
868    refine lift_rel_def.2 ⟨_, _⟩,
id            └──────────┘
src    └─────┘└──────────┘└─┘ └───┘
typ    └─────┘└──────────┘└─┘ └───┘
doc    └─────┘            └─┘ └───┘
txt    └─────┘            └─┘ └───┘
par    └─────┘            └─┘ └───┘
pid                      └─┘ └───┘
st   ─────────────────────────────┘└─
869    { rw [←head_terminates_iff, ←head_terminates_iff],
id            └─────────────────┘   └─────────────────┘
src      └───┘└─────────────────┘└─┘└─────────────────┘
typ      └───┘└─────────────────┘└─┘└─────────────────┘
doc      └───┘                   └─┘                   
txt      └───┘                   └─┘                   
par      └───┘                   └─┘                   
pid        └─┘                   └─┘                   
st   ───┘└──────────────────────┘└────────────────────┘└──
870      exact terminates_congr (h 0) },
id             └──────────────┘  
src      └────┘└──────────────┘  └──┘
typ      └────┘└──────────────┘ └──┘
doc      └────┘                  └──┘
txt      └────┘                  └──┘
par      └────┘                  └──┘
pid                             └─┘
st   ────────────────────────────────┘└┘
871    { intros a b ma mb,
src      └──────────────┘
typ      └──────────────┘
doc      └──────────────┘
txt      └──────────────┘
par      └──────────────┘
pid            └────────┘
st   ───────────────────┘└─
872      cases a with a; cases b with b,
id                            
src      └────┘ └─────┘  └────┘ └─────┘
typ      └────┘└─────┘  └────┘└─────┘
doc      └────┘ └─────┘  └────┘ └─────┘
txt      └────┘ └─────┘  └────┘ └─────┘
par      └────┘ └─────┘  └────┘ └─────┘
pid            └─────┘        └─────┘
st   ─────────────────────────────────┘└─
873      { trivial },
src        └──────┘
typ        └──────┘
doc        └──────┘
txt        └──────┘
par        └──────┘
pid               
st   ─────┘└──────┘└┘
874      { injection mem_unique (mem_map _ ma) ((h 0 _).2 (mem_map _ mb)) },
id                   └────────┘            └┘             └─────┘   └┘
src        └────────┘└────────┘        └─┘  └┘   └──────┘ └─────┘└─┘  └─┘
typ        └────────┘└────────┘        └─┘└┘└┘  └──────┘ └─────┘└─┘└┘└─┘
doc        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
txt        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
par        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
pid                                   └─┘  └┘   └──────┘        └─┘  └┘
st   ─────┘└─────────────────────────────────────────────────────────────┘└┘
875      { injection mem_unique (mem_map _ ma) ((h 0 _).2 (mem_map _ mb)) },
id                   └────────┘            └┘             └─────┘   └┘
src        └────────┘└────────┘        └─┘  └┘   └──────┘ └─────┘└─┘  └─┘
typ        └────────┘└────────┘        └─┘└┘└┘  └──────┘ └─────┘└─┘└┘└─┘
doc        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
txt        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
par        └────────┘                  └─┘  └┘   └──────┘        └─┘  └─┘
pid                                   └─┘  └┘   └──────┘        └─┘  └┘
st   ─────┘└─────────────────────────────────────────────────────────────┘└┘
876      { cases a with a s', cases b with b t',
id                                 
src        └────┘ └────────┘  └────┘ └────────┘
typ        └────┘└────────┘  └────┘└────────┘
doc        └────┘ └────────┘  └────┘ └────────┘
txt        └────┘ └────────┘  └────┘ └────────┘
par        └────┘ └────────┘  └────┘ └────────┘
pid              └────────┘        └────────┘
st   ──────────────────────┘└─────────────────┘└─
877        injection mem_unique (mem_map _ ma) ((h 0 _).2 (mem_map _ mb)) with ab,
id                   └────────┘            └┘             └─────┘   └┘
src        └────────┘└────────┘        └─┘  └┘   └──────┘ └─────┘└─┘  └────────┘
typ        └────────┘└────────┘        └─┘└┘└┘  └──────┘ └─────┘└─┘└┘└────────┘
doc        └────────┘                  └─┘  └┘   └──────┘        └─┘  └────────┘
txt        └────────┘                  └─┘  └┘   └──────┘        └─┘  └────────┘
par        └────────┘                  └─┘  └┘   └──────┘        └─┘  └────────┘
pid                                   └─┘  └┘   └──────┘        └─┘  └┘└──────┘
st   ───────────────────────────────────────────────────────────────────────────┘└─
878        refine ⟨ab, λ n, _⟩,
id                 └┘
src        └─────┘   └┘ └────┘
typ        └─────┘ └┘└┘ └────┘
doc        └─────┘   └┘ └────┘
txt        └─────┘   └┘ └────┘
par        └─────┘   └┘ └────┘
pid                 └┘ └────┘
st   ────────────────────────┘└─
879        refine (nth_congr (flatten_equiv (mem_map _ ma)) n).symm.trans
id                                                     └┘
src        └─────┘                                └─┘  └─┘ └────────────
typ        └─────┘                                └─┘└┘└─┘ └────────────
doc        └─────┘                                └─┘  └─┘ └────────────
txt        └─────┘                                └─┘  └─┘ └────────────
par        └─────┘                                └─┘  └─┘ └────────────
pid                                              └─┘  └─┘ └────────────
st   ─────────────────────────────────────────────────────────────────────
880          ((_ : nth (tail s) n ~ nth (tail t) n).trans
id                                └─┘  └──┘ 
src  ───────┘  └──┘         └┘ └─┘ └──┘ └┘ └───────
typ  ───────┘  └──┘        └┘ └─┘ └──┘└┘ └───────
doc  ───────┘  └──┘         └┘ └─┘ └──┘ └┘ └───────
txt  ───────┘  └──┘         └┘           └┘ └───────
par  ───────┘  └──┘         └┘           └┘ └───────
pid  ───────┘  └──┘         └┘           └┘ └───────
st   ─────────────────────────────────────────────────────
881          (nth_congr (flatten_equiv (mem_map _ mb)) n)),
id            └───────┘  └───────────┘  └─────┘   └┘   
src  ───────┘ └───────┘ └───────────┘ └─────┘└─┘  └─┘ └┘
typ  ───────┘ └───────┘ └───────────┘ └─────┘└─┘└┘└─┘└┘
doc  ───────┘                                └─┘  └─┘ └┘
txt  ───────┘                                └─┘  └─┘ └┘
par  ───────┘                                └─┘  └─┘ └┘
pid  ───────┘                                └─┘  └─┘ └┘
st   ────────────────────────────────────────────────────┘└─
882        rw [nth_tail, nth_tail], apply h } }
id             └──────┘  └──────┘
src        └──┘└──────┘└┘└──────┘  └────┘ 
typ        └──┘└──────┘└┘└──────┘  └────┘ 
doc        └──┘        └┘          └────┘ 
txt        └──┘        └┘          └────┘ 
par        └──┘        └┘          └────┘ 
pid          └┘        └┘                
st   ─────────────────┘└────────┘└─────────┘└───
883  end⟩
st   ──┘
884  
885  theorem length_eq_map (s : wseq α) : length s = computation.map list.length (to_list s) :=
id                              └──┘     └────┘   └─────────────┘ └─────────┘  └─────┘ 
src                             └──┘      └────┘    └─────────────┘ └─────────┘  └─────┘
typ                             └──┘     └────┘   └─────────────┘ └─────────┘  └─────┘ 
doc                             └──┘      └────┘     └─────────────┘              └─────┘
886  begin
st   └─────
887    refine eq_of_bisim
id            └─────────┘
src    └─────┘└─────────┘
typ    └─────┘└─────────┘
doc    └─────┘           
txt    └─────┘           
par    └─────┘           
pid                     
st   ─────────────────────
888      (λ c1 c2, ∃ (l : list α) (s : wseq α),
id                       └──┘         └──┘  
src  ───┘  └──────┘└────┘└──┘ └─────┘└──┘ 
typ  ───┘  └──────┘└────┘└──┘ └─────┘└──┘
doc  ───┘  └──────┘ └────┘     └─────┘└──┘  
txt  ───┘  └──────┘ └────┘     └─────┘      
par  ───┘  └──────┘ └────┘     └─────┘      
pid  ───┘  └──────┘ └────┘     └─────┘      
st   ───────────────────────────────────────────
889        c1 = corec length._match_2 (l.length, s) ∧
id                   └─────────────┘   └─────┘     
src  ─────┘       └─────────────┘  └─────┘└┘ └┘
typ  ─────┘       └─────────────┘  └─────┘└┘ └┘
doc  ─────┘                                └┘ └┘ 
txt  ─────┘                                └┘ └┘ 
par  ─────┘                                └┘ └┘ 
pid  ─────┘                                └┘ └┘ 
st   ─────────────────────────────────────────────────
890        c2 = computation.map list.length (corec to_list._match_2 (l, s)))
id              └─────────────┘ └─────────┘  └───┘ └──────────────┘
src  ─────┘   └─────────────┘└─────────┘ └───┘└──────────────┘  └┘ └───
typ  ─────┘   └─────────────┘└─────────┘ └───┘└──────────────┘  └┘ └───
doc  ─────┘   └─────────────┘            └───┘                  └┘ └───
txt  ─────┘                                                     └┘ └───
par  ─────┘                                                     └┘ └───
pid  ─────┘                                                     └┘ └───
st   ────────────────────────────────────────────────────────────────────────
891      _ ⟨[], s, rfl, rfl⟩,
id                     └─┘
src  ─────┘   └┘ └┘   └┘└─┘
typ  ─────┘   └┘└┘   └┘└─┘
doc  ─────┘   └┘ └┘   └┘   
txt  ─────┘   └┘ └┘   └┘   
par  ─────┘   └┘ └┘   └┘   
pid  ─────┘   └┘ └┘   └┘   
st   ──────────────────────┘└─
892    intros s1 s2 h, rcases h with ⟨l, s, h⟩, rw [h.left, h.right],
id                            
src    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
typ    └────────────┘  └─────┘└─────────────┘  └──┘└────┘└┘└─────┘
doc    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
txt    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
par    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
pid          └──────┘         └─────────────┘    └┘      └┘       
st   ───────────────┘└───────────────────────┘└──────────┘└───────┘└──
893    apply s.cases_on _ (λ a s, _) (λ s, _);
id           └────────┘
src    └────┘└────────┘└─┘  └───────┘  └────┘
typ    └────┘└────────┘└─┘  └───────┘  └────┘
doc    └────┘          └─┘  └───────┘  └────┘
txt    └────┘          └─┘  └───────┘  └────┘
par    └────┘          └─┘  └───────┘  └────┘
pid                   └─┘  └───────┘  └────┘
st   ──────────────────────────────────────────
894      repeat {simp [to_list, nil, cons, think, length]},
id                     └─────┘  └─┘  └──┘  └───┘  └────┘
src      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
typ      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
doc      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
txt      └──────┘└────┘       └┘   └┘    └┘     └┘      
par      └──────┘└────┘       └┘   └┘    └┘     └┘      
pid            └──────┘       └┘   └┘    └┘     └┘      └┘
st   ───────────┘└──────────────────────────────────────┘└┘
895    { refine ⟨a::l, s, _, _⟩; simp },
id                   
src      └─────┘     └┘ └─────┘  └───┘
typ      └─────┘   └┘└─────┘  └───┘
doc      └─────┘     └┘ └─────┘  └───┘
txt      └─────┘     └┘ └─────┘  └───┘
par      └─────┘     └┘ └─────┘  └───┘
pid                 └┘ └─────┘      
st   ───┘└───────────────────────────┘└┘
896    { refine ⟨l, s, _, _⟩; simp }
id                 
src      └─────┘  └┘ └─────┘  └───┘
typ      └─────┘ └┘└─────┘  └───┘
doc      └─────┘  └┘ └─────┘  └───┘
txt      └─────┘  └┘ └─────┘  └───┘
par      └─────┘  └┘ └─────┘  └───┘
pid              └┘ └─────┘      
st   ─────────────────────────────┘└─
897  end
st   ──┘
898  
899  @[simp] theorem of_list_nil : of_list [] = (nil : wseq α) := rfl
id                                 └─────┘ └┘   └─┘   └──┘      └─┘
src                                └─────┘ └┘   └─┘   └──┘       └─┘
typ                                └─────┘ └┘   └─┘   └──┘      └─┘
doc    └──┘                        └─────┘       └─┘   └──┘
900  
901  @[simp] theorem of_list_cons (a : α) (l) :
id                                     
typ                                    
doc    └──┘
902    of_list (a :: l) = cons a (of_list l) :=
id     └─────┘   └┘    └──┘   └─────┘ 
src    └─────┘    └┘     └──┘    └─────┘
typ    └─────┘   └┘    └──┘   └─────┘ 
doc    └─────┘            └──┘    └─────┘
903  show seq.map some (seq.of_list (a :: l)) =
id        └─────┘ └──┘  └─────────┘   └┘    
src       └─────┘ └──┘  └─────────┘    └┘     
typ       └─────┘ └──┘  └─────────┘   └┘    
doc       └─────┘       └─────────┘
904       seq.cons (some a) (seq.map some (seq.of_list l)), by simp
id        └──────┘  └──┘    └─────┘ └──┘  └─────────┘ 
src       └──────┘  └──┘     └─────┘ └──┘  └─────────┘         └────
typ       └──────┘  └──┘    └─────┘ └──┘  └─────────┘        └────
doc       └──────┘           └─────┘       └─────────┘         └────
txt                                                            └────
par                                                            └────
pid                                                                
st                                                            └─────
905  
src  
typ  
doc  
txt  
par  
pid  
st   
906  @[simp] theorem to_list'_nil (l : list α) :
id                                     └──┘ 
src                                    └──┘
typ                                    └──┘ 
doc    └──┘
907    corec to_list._match_2 (l, nil) = return l.reverse :=
id     └───┘ └──────────────┘   └─┘   └────┘ └──────┘
src    └───┘ └──────────────┘    └─┘   └────┘  └──────┘
typ    └───┘ └──────────────┘   └─┘   └────┘ └──────┘
doc    └───┘                      └─┘    └────┘
908  destruct_eq_ret rfl
id   └─────────────┘ └─┘
src  └─────────────┘ └─┘
typ  └─────────────┘ └─┘
909  
910  @[simp] theorem to_list'_cons (l : list α) (s : wseq α) (a : α) :
id                                      └──┘        └──┘        
src                                     └──┘         └──┘
typ                                     └──┘        └──┘        
doc    └──┘                                          └──┘
911    corec to_list._match_2 (l, cons a s) =
id     └───┘ └──────────────┘   └──┘    
src    └───┘ └──────────────┘    └──┘      
typ    └───┘ └──────────────┘   └──┘    
doc    └───┘                      └──┘
912    (corec to_list._match_2 (a::l, s)).think :=
id      └───┘ └──────────────┘ └┘    └───┘
src     └───┘ └──────────────┘  └┘      └───┘
typ     └───┘ └──────────────┘ └┘    └───┘
doc     └───┘                            └───┘
913  destruct_eq_think $ by simp [to_list, cons]
id   └───────────────┘            └─────┘  └──┘
src  └───────────────┘      └────┘└─────┘└┘└──┘└─
typ  └───────────────┘      └────┘└─────┘└┘└──┘└─
doc                         └────┘└─────┘└┘└──┘└─
txt                         └────┘       └┘    └─
par                         └────┘       └┘    └─
pid                                    └┘    
st                         └─────────────────────
914  
src  
typ  
doc  
txt  
par  
pid  
st   
915  @[simp] theorem to_list'_think (l : list α) (s : wseq α) :
id                                       └──┘        └──┘ 
src                                      └──┘         └──┘
typ                                      └──┘        └──┘ 
doc    └──┘                                           └──┘
916    corec to_list._match_2 (l, think s) =
id     └───┘ └──────────────┘   └───┘   
src    └───┘ └──────────────┘    └───┘    
typ    └───┘ └──────────────┘   └───┘   
doc    └───┘                      └───┘
917    (corec to_list._match_2 (l, s)).think :=
id      └───┘ └──────────────┘     └───┘
src     └───┘ └──────────────┘       └───┘
typ     └───┘ └──────────────┘     └───┘
doc     └───┘                         └───┘
918  destruct_eq_think $ by simp [to_list, think]
id   └───────────────┘            └─────┘  └───┘
src  └───────────────┘      └────┘└─────┘└┘└───┘└─
typ  └───────────────┘      └────┘└─────┘└┘└───┘└─
doc                         └────┘└─────┘└┘└───┘└─
txt                         └────┘       └┘     └─
par                         └────┘       └┘     └─
pid                                    └┘     
st                         └──────────────────────
919  
src  
typ  
doc  
txt  
par  
pid  
st   
920  theorem to_list'_map (l : list α) (s : wseq α) :
id                             └──┘        └──┘ 
src                            └──┘         └──┘
typ                            └──┘        └──┘ 
doc                                         └──┘
921    corec to_list._match_2 (l, s) =
id     └───┘ └──────────────┘     
src    └───┘ └──────────────┘       
typ    └───┘ └──────────────┘     
doc    └───┘
922    ((++) l.reverse) <$> to_list s :=
id          └──────┘  └─┘ └─────┘ 
src          └──────┘  └─┘ └─────┘
typ         └──────┘  └─┘ └─────┘ 
doc                         └─────┘
923  begin
st   └─────
924    refine eq_of_bisim
id            └─────────┘
src    └─────┘└─────────┘
typ    └─────┘└─────────┘
doc    └─────┘           
txt    └─────┘           
par    └─────┘           
pid                     
st   ─────────────────────
925      (λ c1 c2, ∃ (l' : list α) (s : wseq α),
id                        └──┘         └──┘  
src  ───┘  └──────┘└─────┘└──┘ └─────┘└──┘ 
typ  ───┘  └──────┘└─────┘└──┘ └─────┘└──┘
doc  ───┘  └──────┘ └─────┘     └─────┘└──┘  
txt  ───┘  └──────┘ └─────┘     └─────┘      
par  ───┘  └──────┘ └─────┘     └─────┘      
pid  ───┘  └──────┘ └─────┘     └─────┘      
st   ────────────────────────────────────────────
926        c1 = corec to_list._match_2 (l' ++ l, s) ∧
id                                        └┘       
src  ─────┘                          └┘ └┘ └┘
typ  ─────┘                          └┘ └┘ └┘
doc  ─────┘                              └┘ └┘ 
txt  ─────┘                              └┘ └┘ 
par  ─────┘                              └┘ └┘ 
pid  ─────┘                              └┘ └┘ 
st   ─────────────────────────────────────────────────
927        c2 = computation.map ((++) l.reverse) (corec to_list._match_2 (l', s)))
id              └─────────────┘       └───────┘   └───┘ └──────────────┘
src  ─────┘   └─────────────┘  └──┘└───────┘└┘ └───┘└──────────────┘   └┘ └───
typ  ─────┘   └─────────────┘  └──┘└───────┘└┘ └───┘└──────────────┘   └┘ └───
doc  ─────┘   └─────────────┘  └──┘         └┘ └───┘                   └┘ └───
txt  ─────┘                    └──┘         └┘                         └┘ └───
par  ─────┘                    └──┘         └┘                         └┘ └───
pid  ─────┘                    └──┘         └┘                         └┘ └───
st   ──────────────────────────────────────────────────────────────────────────────
928      _ ⟨[], s, rfl, rfl⟩,
id                     └─┘
src  ─────┘   └┘ └┘   └┘└─┘
typ  ─────┘   └┘└┘   └┘└─┘
doc  ─────┘   └┘ └┘   └┘   
txt  ─────┘   └┘ └┘   └┘   
par  ─────┘   └┘ └┘   └┘   
pid  ─────┘   └┘ └┘   └┘   
st   ──────────────────────┘└─
929    intros s1 s2 h, rcases h with ⟨l', s, h⟩, rw [h.left, h.right],
id                            
src    └────────────┘  └─────┘ └──────────────┘  └──┘      └┘       
typ    └────────────┘  └─────┘└──────────────┘  └──┘└────┘└┘└─────┘
doc    └────────────┘  └─────┘ └──────────────┘  └──┘      └┘       
txt    └────────────┘  └─────┘ └──────────────┘  └──┘      └┘       
par    └────────────┘  └─────┘ └──────────────┘  └──┘      └┘       
pid          └──────┘         └──────────────┘    └┘      └┘       
st   ───────────────┘└────────────────────────┘└──────────┘└───────┘└──
930    apply s.cases_on _ (λ a s, _) (λ s, _);
id           └────────┘
src    └────┘└────────┘└─┘  └───────┘  └────┘
typ    └────┘└────────┘└─┘  └───────┘  └────┘
doc    └────┘          └─┘  └───────┘  └────┘
txt    └────┘          └─┘  └───────┘  └────┘
par    └────┘          └─┘  └───────┘  └────┘
pid                   └─┘  └───────┘  └────┘
st   ──────────────────────────────────────────
931      repeat {simp [to_list, nil, cons, think, length]},
id                     └─────┘  └─┘  └──┘  └───┘  └────┘
src      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
typ      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
doc      └──────┘└────┘└─────┘└┘└─┘└┘└──┘└┘└───┘└┘└────┘
txt      └──────┘└────┘       └┘   └┘    └┘     └┘      
par      └──────┘└────┘       └┘   └┘    └┘     └┘      
pid            └──────┘       └┘   └┘    └┘     └┘      └┘
st   ───────────┘└──────────────────────────────────────┘└┘
932    { refine ⟨a::l', s, _, _⟩; simp },
id                 └┘  
src      └─────┘      └┘ └─────┘  └───┘
typ      └─────┘   └┘└┘└─────┘  └───┘
doc      └─────┘      └┘ └─────┘  └───┘
txt      └─────┘      └┘ └─────┘  └───┘
par      └─────┘      └┘ └─────┘  └───┘
pid                  └┘ └─────┘      
st   ───┘└────────────────────────────┘└┘
933    { refine ⟨l', s, _, _⟩; simp }
id               └┘  
src      └─────┘   └┘ └─────┘  └───┘
typ      └─────┘ └┘└┘└─────┘  └───┘
doc      └─────┘   └┘ └─────┘  └───┘
txt      └─────┘   └┘ └─────┘  └───┘
par      └─────┘   └┘ └─────┘  └───┘
pid               └┘ └─────┘      
st   ──────────────────────────────┘└─
934  end
st   ──┘
935  
936  @[simp] theorem to_list_cons (a : α) (s) :
id                                     
typ                                    
doc    └──┘
937    to_list (cons a s) = (list.cons a <$> to_list s).think :=
id     └─────┘  └──┘      └───────┘  └─┘ └─────┘  └───┘
src    └─────┘  └──┘        └───────┘   └─┘ └─────┘   └───┘
typ    └─────┘  └──┘      └───────┘  └─┘ └─────┘  └───┘
doc    └─────┘  └──┘                         └─────┘   └───┘
938  destruct_eq_think $ by unfold to_list; simp; rw to_list'_map; simp; refl
id   └───────────────┘                               └──────────┘
src  └───────────────┘      └────────────┘  └──┘  └─┘└──────────┘  └──┘  └────
typ  └───────────────┘      └────────────┘  └──┘  └─┘└──────────┘  └──┘  └────
doc                         └────────────┘  └──┘  └─┘              └──┘  └────
txt                         └────────────┘  └──┘  └─┘              └──┘  └────
par                         └────────────┘  └──┘  └─┘              └──┘  └────
pid                               └──────┘                                  
st                         └────────────────────────┘└──────────┘└────────────
939  
src  
typ  
doc  
txt  
par  
pid  
st   
940  @[simp] theorem to_list_nil : to_list (nil : wseq α) = return [] :=
id                                 └─────┘  └─┘   └──┘    └────┘ └┘
src                                └─────┘  └─┘   └──┘     └────┘ └┘
typ                                └─────┘  └─┘   └──┘    └────┘ └┘
doc    └──┘                        └─────┘  └─┘   └──┘      └────┘
941  destruct_eq_ret rfl
id   └─────────────┘ └─┘
src  └─────────────┘ └─┘
typ  └─────────────┘ └─┘
942  
943  theorem to_list_of_list (l : list α) : l ∈ to_list (of_list l) :=
id                                └──┘       └─────┘  └─────┘ 
src                               └──┘         └─────┘  └─────┘
typ                               └──┘       └─────┘  └─────┘ 
doc                                             └─────┘  └─────┘
944  by induction l with a l IH; simp [ret_mem]; exact think_mem (mem_map _ IH)
id                                    └─────┘         └───────┘  └─────┘   └┘
src     └────────┘ └──────────┘  └────┘└─────┘  └────┘└───────┘ └─────┘└─┘  └─
typ     └────────┘└──────────┘  └────┘└─────┘  └────┘└───────┘ └─────┘└─┘└┘└─
doc     └────────┘ └──────────┘  └────┘         └────┘                 └─┘  └─
txt     └────────┘ └──────────┘  └────┘         └────┘                 └─┘  └─
par     └────────┘ └──────────┘  └────┘         └────┘                 └─┘  └─
pid               └─────────┘                                     └─┘  
st     └────────────────────────────────────────────────────────────────────────
945  
src  
typ  
doc  
txt  
par  
pid  
st   
946  @[simp] theorem destruct_of_seq (s : seq α) :
id                                        └─┘ 
src                                       └─┘
typ                                       └─┘ 
doc    └──┘                               └─┘
947    destruct (of_seq s) = return (s.head.map $ λ a, (a, of_seq s.tail)) :=
id     └──────┘  └────┘    └────┘  └───┘└──┘         └────┘ └───┘
src    └──────┘  └────┘     └────┘   └───┘└──┘           └────┘  └───┘
typ    └──────┘  └────┘    └────┘  └───┘└──┘         └────┘ └───┘
doc    └──────┘  └────┘      └────┘   └───┘                └────┘  └───┘
948  destruct_eq_ret $ begin
id   └─────────────┘
src  └─────────────┘
typ  └─────────────┘
st                     └─────
949    simp [of_seq, head, destruct, seq.destruct, seq.head],
id           └────┘  └──┘  └──────┘  └──────────┘  └──────┘
src    └────┘└────┘└┘└──┘└┘└──────┘└┘└──────────┘└┘└──────┘
typ    └────┘└────┘└┘└──┘└┘└──────┘└┘└──────────┘└┘└──────┘
doc    └────┘└────┘└┘└──┘└┘└──────┘└┘└──────────┘└┘└──────┘
txt    └────┘      └┘    └┘        └┘            └┘        
par    └────┘      └┘    └┘        └┘            └┘        
pid              └┘    └┘        └┘            └┘        
st   ──────────────────────────────────────────────────────┘└─
950    rw [show seq.nth (some <$> s) 0 = some <$> seq.nth s 0, by apply seq.map_nth],
id                            └─┘       └──┘     └─────┘              └─────────┘
src    └──┘                └─┘ └──┘└──┘   └─────┘ └─────┘└────┘└─────────┘
typ    └──┘                └─┘ └──┘└──┘   └─────┘└─────┘└────┘└─────────┘
doc    └──┘                    └──┘        └─────┘ └─────┘└────┘           
txt    └──┘                    └──┘                └─────┘└────┘           
par    └──┘                    └──┘                └─────┘└────┘           
pid      └┘                    └──┘                └───────────┘           
st   ───────────────────────────────────────────────────────────┘└────────────────┘└──
951    cases seq.nth s 0 with a, { refl },
id           └─────┘ 
src    └────┘└─────┘ └───────┘    └───┘
typ    └────┘└─────┘└───────┘    └───┘
doc    └────┘└─────┘ └───────┘    └───┘
txt    └────┘        └───────┘    └───┘
par    └────┘        └───────┘    └───┘
pid                 └──────┘        
st   ─────────────────────────┘└──┘└───┘└┘
952    unfold functor.map,
src    └────────────────┘
typ    └────────────────┘
doc    └────────────────┘
txt    └────────────────┘
par    └────────────────┘
pid          └──────────┘
st   ───────────────────┘└─
953    simp [destruct]
id           └──────┘
src    └────┘└──────┘└┘
typ    └────┘└──────┘└┘
doc    └────┘└──────┘└┘
txt    └────┘        └┘
par    └────┘        └┘
pid                
st   ─────────────────┘
954  end
st   └─┘
955  
956  @[simp] theorem head_of_seq (s : seq α) : head (of_seq s) = return s.head :=
id                                    └─┘     └──┘  └────┘    └────┘ └───┘
src                                   └─┘      └──┘  └────┘     └────┘  └───┘
typ                                   └─┘     └──┘  └────┘    └────┘ └───┘
doc    └──┘                           └─┘      └──┘  └────┘      └────┘  └───┘
957  by simp [head]; cases seq.head s; refl
id            └──┘         └──────┘ 
src     └────┘└──┘  └────┘└──────┘   └────
typ     └────┘└──┘  └────┘└──────┘  └────
doc     └────┘└──┘  └────┘└──────┘   └────
txt     └────┘      └────┘           └────
par     └────┘      └────┘           └────
pid                                   
st     └────────────────────────────────────
958  
src  
typ  
doc  
txt  
par  
pid  
st   
959  @[simp] theorem tail_of_seq (s : seq α) : tail (of_seq s) = of_seq s.tail :=
id                                    └─┘     └──┘  └────┘    └────┘ └───┘
src                                   └─┘      └──┘  └────┘     └────┘  └───┘
typ                                   └─┘     └──┘  └────┘    └────┘ └───┘
doc    └──┘                           └─┘      └──┘  └────┘      └────┘  └───┘
960  begin
st   └─────
961    simp [tail], apply s.cases_on _ (λ x s, _); simp [of_seq], {refl},
id           └──┘         └────────┘                     └────┘
src    └────┘└──┘  └────┘└────────┘└─┘  └──────┘  └────┘└────┘   └──┘
typ    └────┘└──┘  └────┘└────────┘└─┘  └──────┘  └────┘└────┘   └──┘
doc    └────┘└──┘  └────┘          └─┘  └──────┘  └────┘└────┘   └──┘
txt    └────┘      └────┘          └─┘  └──────┘  └────┘         └──┘
par    └────┘      └────┘          └─┘  └──────┘  └────┘         └──┘
pid                             └─┘  └──────┘            
st   ────────────┘└────────────────────────────────────────────┘└─────┘└┘
962    rw [seq.head_cons, seq.tail_cons], refl
id         └───────────┘  └───────────┘
src    └──┘└───────────┘└┘└───────────┘  └───┘
typ    └──┘└───────────┘└┘└───────────┘  └───┘
doc    └──┘             └┘               └───┘
txt    └──┘             └┘               └───┘
par    └──┘             └┘               └───┘
pid      └┘             └┘                   
st   ──────────────────┘└─────────────┘└──────┘
963  end
st   └─┘
964  
965  @[simp] theorem dropn_of_seq (s : seq α) : ∀ n, drop (of_seq s) n = of_seq (s.drop n)
id                                     └─┘         └──┘  └────┘     └────┘  └───┘ 
src                                    └─┘           └──┘  └────┘       └────┘   └───┘
typ                                    └─┘         └──┘  └────┘     └────┘  └───┘ 
doc    └──┘                            └─┘           └──┘  └────┘        └────┘   └───┘
966  | 0 := rfl
id          └─┘
src         └─┘
typ         └─┘
967  | (n+1) := by dsimp [drop]; rw [dropn_of_seq, tail_of_seq]
id                       └──┘       └──────────┘  └─────────┘
src               └─────┘└──┘  └──┘            └┘└─────────┘└─
typ               └─────┘└──┘  └──┘└──────────┘└┘└─────────┘└─
doc                └─────┘└──┘  └──┘            └┘           └─
txt                └─────┘      └──┘            └┘           └─
par                └─────┘      └──┘            └┘           └─
pid                             └┘            └┘           
st                └─────────────────┘└──────────┘└───────────┘
968  
src  
typ  
doc  
txt  
par  
pid  
st   
969  theorem nth_of_seq (s : seq α) (n) : nth (of_seq s) n = return (seq.nth s n) :=
id                           └─┘         └─┘  └────┘     └────┘  └─────┘  
src                          └─┘          └─┘  └────┘       └────┘  └─────┘
typ                          └─┘         └─┘  └────┘     └────┘  └─────┘  
doc                          └─┘          └─┘  └────┘        └────┘  └─────┘
970  by dsimp [nth]; rw [dropn_of_seq, head_of_seq, seq.head_dropn]
id             └─┘       └──────────┘  └─────────┘  └────────────┘
src     └─────┘└─┘  └──┘└──────────┘└┘└─────────┘└┘└────────────┘└─
typ     └─────┘└─┘  └──┘└──────────┘└┘└─────────┘└┘└────────────┘└─
doc     └─────┘└─┘  └──┘            └┘           └┘              └─
txt     └─────┘     └──┘            └┘           └┘              └─
par     └─────┘     └──┘            └┘           └┘              └─
pid                 └┘            └┘           └┘              
st     └────────────────┘└──────────┘└───────────┘└──────────────┘
971  
src  
typ  
doc  
txt  
par  
pid  
st   
972  instance productive_of_seq (s : seq α) : productive (of_seq s) :=
id                                   └─┘     └────────┘  └────┘ 
src                                  └─┘      └────────┘  └────┘
typ                                  └─┘     └────────┘  └────┘ 
doc                                  └─┘      └────────┘  └────┘
973  λ n, by rw nth_of_seq; apply_instance
id             └────────┘
src          └─┘└────────┘  └──────────────
typ         └─┘└────────┘  └──────────────
doc          └─┘            └──────────────
txt          └─┘            └──────────────
par          └─┘            └──────────────
pid                                      
st          └──────────────────────────────
974  
src  
typ  
doc  
txt  
par  
pid  
st   
975  theorem to_seq_of_seq (s : seq α) : to_seq (of_seq s) = s :=
id                              └─┘     └────┘  └────┘    
src                             └─┘      └────┘  └────┘    
typ                             └─┘     └────┘  └────┘    
doc                             └─┘      └────┘  └────┘
976  begin
st   └─────
977    apply subtype.eq, funext n,
id           └────────┘
src    └────┘└────────┘  └──────┘
typ    └────┘└────────┘  └──────┘
doc    └────┘            └──────┘
txt    └────┘            └──────┘
par    └────┘            └──────┘
pid                           └┘
st   ─────────────────┘└────────┘└─
978    dsimp [to_seq], apply get_eq_of_mem,
id            └────┘         └───────────┘
src    └─────┘└────┘  └────┘└───────────┘
typ    └─────┘└────┘  └────┘└───────────┘
doc    └─────┘└────┘  └────┘
txt    └─────┘        └────┘
par    └─────┘        └────┘
pid                      
st   ───────────────┘└───────────────────┘└─
979    rw nth_of_seq, apply ret_mem
id        └────────┘        └─────┘
src    └─┘└────────┘  └────┘└─────┘
typ    └─┘└────────┘  └────┘└─────┘
doc    └─┘            └────┘       
txt    └─┘            └────┘       
par    └─┘            └────┘       
pid                              
st   ──────────────┘└──────────────┘
980  end
st   └─┘
981  
982  /-- The monadic `return a` is a singleton list containing `a`. -/
983  def ret (a : α) : wseq α := of_list [a]
id                    └──┘     └─────┘ 
src                    └──┘      └─────┘  
typ                   └──┘     └─────┘ 
doc                    └──┘      └─────┘
984  
985  @[simp] theorem map_nil (f : α → β) : map f nil = nil := rfl
id                                       └─┘  └─┘  └─┘    └─┘
src                                        └─┘   └─┘  └─┘    └─┘
typ                                      └─┘  └─┘  └─┘    └─┘
doc    └──┘                                └─┘   └─┘   └─┘
986  
987  @[simp] theorem map_cons (f : α → β) (a s) :
id                                    
typ                                   
doc    └──┘
988    map f (cons a s) = cons (f a) (map f s) := seq.map_cons _ _ _
id     └─┘   └──┘     └──┘      └─┘       └──────────┘
src    └─┘    └──┘       └──┘        └─┘         └──────────┘
typ    └─┘   └──┘     └──┘      └─┘       └──────────┘
doc    └─┘    └──┘        └──┘        └─┘
989  
990  @[simp] theorem map_think (f : α → β) (s) :
id                                     
typ                                    
doc    └──┘
991    map f (think s) = think (map f s) := seq.map_cons _ _ _
id     └─┘   └───┘    └───┘  └─┘       └──────────┘
src    └─┘    └───┘     └───┘  └─┘         └──────────┘
typ    └─┘   └───┘    └───┘  └─┘       └──────────┘
doc    └─┘    └───┘      └───┘  └─┘
992  
993  @[simp] theorem map_id (s : wseq α) : map id s = s := by simp [map]
id                               └──┘     └─┘ └┘                └─┘
src                              └──┘      └─┘ └┘            └────┘└─┘└─
typ                              └──┘     └─┘ └┘          └────┘└─┘└─
doc    └──┘                      └──┘      └─┘                └────┘└─┘└─
txt                                                           └────┘   └─
par                                                           └────┘   └─
pid                                                                  
st                                                           └───────────
994  
src  
typ  
doc  
txt  
par  
pid  
st   
995  @[simp] theorem map_ret (f : α → β) (a) : map f (ret a) = ret (f a) := by simp [ret]
id                                           └─┘   └─┘    └─┘                 └─┘
src                                            └─┘    └─┘     └─┘             └────┘└─┘└─
typ                                          └─┘   └─┘    └─┘           └────┘└─┘└─
doc    └──┘                                    └─┘    └─┘      └─┘             └────┘└─┘└─
txt                                                                            └────┘   └─
par                                                                            └────┘   └─
pid                                                                                   
st                                                                            └───────────
996  
src  
typ  
doc  
txt  
par  
pid  
st   
997  @[simp] theorem map_append (f : α → β) (s t) : map f (append s t) = append (map f s) (map f t) :=
id                                                └─┘   └────┘     └────┘  └─┘     └─┘  
src                                                 └─┘    └────┘       └────┘  └─┘       └─┘
typ                                               └─┘   └────┘     └────┘  └─┘     └─┘  
doc    └──┘                                         └─┘    └────┘        └────┘  └─┘       └─┘
998  seq.map_append _ _ _
id   └────────────┘
src  └────────────┘
typ  └────────────┘
999  
1000  theorem map_comp (f : α → β) (g : β → γ) (s : wseq α) :
id                                             └──┘ 
src                                                └──┘
typ                                            └──┘ 
doc                                                └──┘
1001    map (g ∘ f) s = map g (map f s) :=
id     └─┘        └─┘   └─┘  
src    └─┘           └─┘    └─┘
typ    └─┘        └─┘   └─┘  
doc    └─┘             └─┘    └─┘
1002  begin
st   └─────
1003    dsimp [map], rw ←seq.map_comp,
id            └─┘       └──────────┘
src    └─────┘└─┘  └──┘└──────────┘
typ    └─────┘└─┘  └──┘└──────────┘
doc    └─────┘└─┘  └──┘
txt    └─────┘     └──┘
par    └─────┘     └──┘
pid                └┘
st   ────────────┘└────────────────┘└─
1004    apply congr_fun, apply congr_arg,
id           └───────┘        └───────┘
src    └────┘└───────┘  └────┘└───────┘
typ    └────┘└───────┘  └────┘└───────┘
doc    └────┘           └────┘
txt    └────┘           └────┘
par    └────┘           └────┘
pid                         
st   ────────────────┘└───────────────┘└─
1005    funext o, cases o; refl
id                     
src    └──────┘  └────┘   └───┘
typ    └──────┘  └────┘  └───┘
doc    └──────┘  └────┘   └───┘
txt    └──────┘  └────┘   └───┘
par    └──────┘  └────┘   └───┘
pid          └┘              
st   ─────────┘└──────────────┘
1006  end
st   └─┘
1007  
1008  theorem mem_map (f : α → β) {a : α} {s : wseq α} : a ∈ s → f a ∈ map f s :=
id                                         └──┘             └─┘  
src                                           └──┘                  └─┘
typ                                        └──┘             └─┘  
doc                                           └──┘                    └─┘
1009  seq.mem_map (option.map f)
id   └─────────┘  └────────┘ 
src  └─────────┘  └────────┘
typ  └─────────┘  └────────┘ 
1010  
1011  -- The converse is not true without additional assumptions
1012  theorem exists_of_mem_join {a : α} : ∀ {S : wseq (wseq α)}, a ∈ join S → ∃ s, s ∈ S ∧ a ∈ s :=
id                                              └──┘  └──┘       └──┘            
src                                              └──┘  └──┘         └──┘                
typ                                             └──┘  └──┘       └──┘            
doc                                              └──┘  └──┘          └──┘
1013  suffices ∀ ss : wseq α, a ∈ ss → ∀ s S, append s (join S) = ss →
id                   └──┘     └┘        └────┘   └──┘    └┘
src                  └──┘                   └────┘    └──┘    
typ                  └──┘     └┘        └────┘   └──┘    └┘
doc                  └──┘                    └────┘    └──┘
1014    a ∈ append s (join S) → a ∈ s ∨ ∃ s, s ∈ S ∧ a ∈ s, from λ S h,
id       └────┘   └──┘                           
src       └────┘    └──┘                       
typ      └────┘   └──┘                           
doc        └────┘    └──┘
1015    (this _ h nil S (by simp) (by simp [h])).resolve_left (not_mem_nil _),
id      └──┘    └─┘                         └──────────┘   └─────────┘
src              └─┘       └──┘      └────┘   └──────────┘   └─────────┘
typ     └──┘    └─┘      └──┘      └────┘  └──────────┘   └─────────┘
doc              └─┘       └──┘      └────┘ 
txt                        └──┘      └────┘ 
par                        └──┘      └────┘ 
pid                                       
st                        └───┘     └───────┘
1016  begin
st   └─────
1017    intros ss h, apply mem_rec_on h (λ b ss o, _) (λ ss IH, _); intros s S,
id                        └────────┘ 
src    └─────────┘  └────┘└────────┘   └──────────┘  └────────┘  └────────┘
typ    └─────────┘  └────┘└────────┘  └──────────┘  └────────┘  └────────┘
doc    └─────────┘  └────┘             └──────────┘  └────────┘  └────────┘
txt    └─────────┘  └────┘             └──────────┘  └────────┘  └────────┘
par    └─────────┘  └────┘             └──────────┘  └────────┘  └────────┘
pid          └───┘                    └──────────┘  └────────┘        └──┘
st   ────────────┘└─────────────────────────────────────────────────────────┘└─
1018    { refine s.cases_on (S.cases_on _ (λ s S, _) (λ S, _)) (λ b' s, _) (λ s, _);
id              └────────┘  └────────┘
src      └─────┘└────────┘ └────────┘└─┘  └───────┘  └──────┘  └────────┘  └────┘
typ      └─────┘└────────┘ └────────┘└─┘  └───────┘  └──────┘  └────────┘  └────┘
doc      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
txt      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
par      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
pid                                 └─┘  └───────┘  └──────┘  └────────┘  └────┘
st   ───┘└──────────────────────────────────────────────────────────────────────────
1019      intros ej m; simp at ej;
src      └─────────┘  └────────┘
typ      └─────────┘  └────────┘
doc      └─────────┘  └────────┘
txt      └─────────┘  └────────┘
par      └─────────┘  └────────┘
pid            └───┘      └───┘
st   ─────────────────────────────
1020      have := congr_arg seq.destruct ej; simp at this;
id               └───────┘ └──────────┘ └┘
src      └──────┘└───────┘└──────────┘    └──────────┘
typ      └──────┘└───────┘└──────────┘└┘  └──────────┘
doc      └──────┘         └──────────┘    └──────────┘
txt      └──────┘                         └──────────┘
par      └──────┘                         └──────────┘
pid      └───┘└─┘                             └─────┘
st   ─────────────────────────────────────────────────────
1021      try {cases this}; try {contradiction},
id                  └──┘
src      └───┘└────┘      └───┘└───────────┘
typ      └───┘└────┘└──┘  └───┘└───────────┘
doc      └───┘└────┘      └───┘└───────────┘
txt      └───┘└────┘      └───┘└───────────┘
par      └───┘└────┘      └───┘└───────────┘
pid         └──────┘         └──────────────┘
st   ────────┘└────────┘└┘└────┘└───────────┘ └─
1022      substs b' ss,
src      └──────────┘
typ      └──────────┘
doc      └──────────┘
txt      └──────────┘
par      └──────────┘
pid            └────┘
st   ───────────────┘└─
1023      simp at m ⊢,
src      └─────────┘
typ      └─────────┘
doc      └─────────┘
txt      └─────────┘
par      └─────────┘
pid          └────┘
st   ──────────────┘└─
1024      cases o with e IH, { simp [e] },
id                                 
src      └────┘ └────────┘    └────┘ └┘
typ      └────┘└────────┘    └────┘└┘
doc      └────┘ └────────┘    └────┘ └┘
txt      └────┘ └────────┘    └────┘ └┘
par      └────┘ └────────┘    └────┘ └┘
pid            └────────┘         
st   ────────────────────┘└──┘└───────┘└┘
1025      cases m with e m, { simp [e] },
id                                
src      └────┘ └───────┘    └────┘ └┘
typ      └────┘└───────┘    └────┘└┘
doc      └────┘ └───────┘    └────┘ └┘
txt      └────┘ └───────┘    └────┘ └┘
par      └────┘ └───────┘    └────┘ └┘
pid            └───────┘         
st   ───────────────────┘└──┘└───────┘└┘
1026      exact or.imp_left or.inr (IH _ _ rfl m) },
id             └─────────┘ └────┘  └┘     └─┘ 
src      └────┘└─────────┘└────┘   └───┘└─┘ └┘
typ      └────┘└─────────┘└────┘ └┘└───┘└─┘└┘
doc      └────┘                    └───┘    └┘
txt      └────┘                    └───┘    └┘
par      └────┘                    └───┘    └┘
pid                               └───┘    
st   ───────────────────────────────────────────┘└┘
1027    { refine s.cases_on (S.cases_on _ (λ s S, _) (λ S, _)) (λ b' s, _) (λ s, _);
id              └────────┘  └────────┘
src      └─────┘└────────┘ └────────┘└─┘  └───────┘  └──────┘  └────────┘  └────┘
typ      └─────┘└────────┘ └────────┘└─┘  └───────┘  └──────┘  └────────┘  └────┘
doc      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
txt      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
par      └─────┘                     └─┘  └───────┘  └──────┘  └────────┘  └────┘
pid                                 └─┘  └───────┘  └──────┘  └────────┘  └────┘
st   ───────────────────────────────────────────────────────────────────────────────
1028      intros ej m; simp at ej;
src      └─────────┘  └────────┘
typ      └─────────┘  └────────┘
doc      └─────────┘  └────────┘
txt      └─────────┘  └────────┘
par      └─────────┘  └────────┘
pid            └───┘      └───┘
st   ─────────────────────────────
1029      have := congr_arg seq.destruct ej; simp at this;
id               └───────┘ └──────────┘ └┘
src      └──────┘└───────┘└──────────┘    └──────────┘
typ      └──────┘└───────┘└──────────┘└┘  └──────────┘
doc      └──────┘         └──────────┘    └──────────┘
txt      └──────┘                         └──────────┘
par      └──────┘                         └──────────┘
pid      └───┘└─┘                             └─────┘
st   ─────────────────────────────────────────────────────
1030      try { try {have := this.1}, contradiction }; subst ss,
id                          └──┘                            └┘
src      └─────────┘└──────┘    └┘└─┘└────────────┘  └────┘
typ      └─────────┘└──────┘└──┘└┘└─┘└────────────┘  └────┘└┘
doc      └─────────┘└──────┘    └┘└─┘└────────────┘  └────┘
txt      └─────────┘└──────┘    └┘└─┘└────────────┘  └────┘
par      └─────────┘└──────┘    └┘└─┘└────────────┘  └────┘
pid         └──────────────┘    └──────────────────┘       
st   ────────┘└──────────────────┘ └──────────────┘└┘└───────┘└─
1031      { apply or.inr, simp at m ⊢,
id               └────┘
src        └────┘└────┘  └─────────┘
typ        └────┘└────┘  └─────────┘
doc        └────┘        └─────────┘
txt        └────┘        └─────────┘
par        └────┘        └─────────┘
pid                         └────┘
st   ─────┘└──────────┘└───────────┘└─
1032        cases IH s S rfl m with as ex,
id               └┘   └─┘ 
src        └────┘    └─┘ └─────────┘
typ        └────┘└┘└─┘└─────────┘
doc        └────┘        └─────────┘
txt        └────┘        └─────────┘
par        └────┘        └─────────┘
pid                     └─────────┘
st   ──────────────────────────────────┘└─
1033        { exact ⟨s, or.inl rfl, as⟩ },
id                    └────┘ └─┘  └┘
src          └────┘  └┘└────┘└─┘└┘  └┘
typ          └────┘ └┘└────┘└─┘└┘└┘└┘
doc          └────┘  └┘         └┘  └┘
txt          └────┘  └┘         └┘  └┘
par          └────┘  └┘         └┘  └┘
pid                 └┘         └┘  
st   ───────┘└────────────────────────┘└┘
1034        { rcases ex with ⟨s', sS, as⟩,
id                  └┘
src          └─────┘  └────────────────┘
typ          └─────┘└┘└────────────────┘
doc          └─────┘  └────────────────┘
txt          └─────┘  └────────────────┘
par          └─────┘  └────────────────┘
pid                  └────────────────┘
st   ──────────────────────────────────┘└─
1035          exact ⟨s', or.inr sS, as⟩ } },
id                  └┘  └────┘ └┘  └┘
src          └────┘   └┘└────┘  └┘  └┘
typ          └────┘ └┘└┘└────┘└┘└┘└┘└┘
doc          └────┘   └┘        └┘  └┘
txt          └────┘   └┘        └┘  └┘
par          └────┘   └┘        └┘  └┘
pid                  └┘        └┘  
st   ─────────────────────────────────┘└──┘
1036      { apply or.inr, simp at m,
id               └────┘
src        └────┘└────┘  └───────┘
typ        └────┘└────┘  └───────┘
doc        └────┘        └───────┘
txt        └────┘        └───────┘
par        └────┘        └───────┘
pid                         └──┘
st   ─────┘└──────────┘└─────────┘└─
1037        rcases (IH nil S (by simp) (by simp [m])).resolve_left (not_mem_nil _) with ⟨s, sS, as⟩,
id                 └┘ └─┘                                        └─────────┘
src        └─────┘   └─┘    └──┘└┘   └────┘ └──────────────┘ └─────────┘└──────────────────┘
typ        └─────┘ └┘└─┘   └──┘└┘   └────┘└──────────────┘ └─────────┘└──────────────────┘
doc        └─────┘   └─┘    └──┘└┘   └────┘ └──────────────┘            └──────────────────┘
txt        └─────┘          └──┘└┘   └────┘ └──────────────┘            └──────────────────┘
par        └─────┘          └──┘└┘   └────┘ └──────────────┘            └──────────────────┘
pid                        └─────┘   └─────┘ └───────────────┘            └──────────────────┘
st   ─────────────────────────┘└───┘└───┘└───────┘└──────────────────────────────────────────────┘└─
1038        exact ⟨s, by simp [sS], as⟩ },
id                           └┘   └┘
src        └────┘  └┘  └────┘  └┘  └┘
typ        └────┘ └┘  └────┘└┘└┘└┘└┘
doc        └────┘  └┘  └────┘  └┘  └┘
txt        └────┘  └┘  └────┘  └┘  └┘
par        └────┘  └┘  └────┘  └┘  └┘
pid               └┘  └─────┘  └─┘  
st   ─────────────────┘└────────┘└────┘└┘
1039      { simp at m IH ⊢, apply IH _ _ rfl m } }
id                               └┘     └─┘ 
src        └────────────┘  └────┘  └───┘└─┘ 
typ        └────────────┘  └────┘└┘└───┘└─┘
doc        └────────────┘  └────┘  └───┘    
txt        └────────────┘  └────┘  └───┘    
par        └────────────┘  └────┘  └───┘    
pid            └───────┘         └───┘    
st   ───────────────────┘└───────────────────┘└───
1040  end
st   ──┘
1041  
1042  theorem exists_of_mem_bind {s : wseq α} {f : α → wseq β} {b}
id                                   └──┘           └──┘ 
src                                  └──┘             └──┘
typ                                  └──┘           └──┘ 
doc                                  └──┘             └──┘
1043    (h : b ∈ bind s f) : ∃ a ∈ s, b ∈ f a :=
id            └──┘              
src            └──┘                 
typ           └──┘              
doc             └──┘
1044  let ⟨t, tm, bt⟩ := exists_of_mem_join h,
id   └─┘     └┘         └────────────────┘ 
src                     └────────────────┘
typ  └─┘     └┘         └────────────────┘ 
1045      ⟨a, as, e⟩ := exists_of_mem_map tm in ⟨a, as, by rwa e⟩
id          └┘        └───────────────┘                      
src                    └───────────────┘                  └──┘
typ         └┘        └───────────────┘                  └──┘
doc                                                       └──┘
txt                                                       └──┘
par                                                       └──┘
pid                                                          
st                                                       └────┘
1046  
1047  theorem destruct_map (f : α → β) (s : wseq α) :
id                                       └──┘ 
src                                        └──┘
typ                                      └──┘ 
doc                                        └──┘
1048    destruct (map f s) = computation.map (option.map (prod.map f (map f))) (destruct s) :=
id     └──────┘  └─┘     └─────────────┘  └────────┘  └──────┘   └─┘      └──────┘ 
src    └──────┘  └─┘       └─────────────┘  └────────┘  └──────┘    └─┘       └──────┘
typ    └──────┘  └─┘     └─────────────┘  └────────┘  └──────┘   └─┘      └──────┘ 
doc    └──────┘  └─┘        └─────────────┘                          └─┘       └──────┘
1049  begin
st   └─────
1050    apply eq_of_bisim (λ c1 c2, ∃ s, c1 = destruct (map f s) ∧
id           └─────────┘                                     
src    └────┘└─────────┘  └──────┘└┘                └┘
typ    └────┘└─────────┘  └──────┘└┘                └┘
doc    └────┘             └──────┘ └┘                  └┘ 
txt    └────┘             └──────┘ └┘                  └┘ 
par    └────┘             └──────┘ └┘                  └┘ 
pid                      └──────┘ └┘                  └┘ 
st   ─────────────────────────────────────────────────────────────
1051      c2 = computation.map (option.map (prod.map f (map f))) (destruct s)),
id            └─────────────┘  └────────┘  └──────┘    └─┘      └──────┘
src  ───┘   └─────────────┘ └────────┘ └──────┘  └─┘ └──┘ └──────┘ └┘
typ  ───┘   └─────────────┘ └────────┘ └──────┘  └─┘└──┘ └──────┘ └┘
doc  ───┘   └─────────────┘                      └─┘ └──┘ └──────┘ └┘
txt  ───┘                                            └──┘          └┘
par  ───┘                                            └──┘          └┘
pid  ───┘                                            └──┘          └┘
st   ───────────────────────────────────────────────────────────────────────┘└─
1052    { intros c1 c2 h, cases h with s h, rw [h.left, h.right],
id                             
src      └────────────┘  └────┘ └───────┘  └──┘      └┘       
typ      └────────────┘  └────┘└───────┘  └──┘└────┘└┘└─────┘
doc      └────────────┘  └────┘ └───────┘  └──┘      └┘       
txt      └────────────┘  └────┘ └───────┘  └──┘      └┘       
par      └────────────┘  └────┘ └───────┘  └──┘      └┘       
pid            └──────┘        └───────┘    └┘      └┘       
st   ───┘└────────────┘└────────────────┘└──────────┘└───────┘└──
1053      apply s.cases_on _ (λ a s, _) (λ s, _); simp; simp,
id             └────────┘
src      └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
typ      └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
doc      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
txt      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
par      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
pid                     └─┘  └───────┘  └────┘
st   ─────────────────────────────────────────────────────┘└─
1054      exact ⟨s, rfl, rfl⟩ },
id                     └─┘
src      └────┘  └┘   └┘└─┘└┘
typ      └────┘ └┘   └┘└─┘└┘
doc      └────┘  └┘   └┘   └┘
txt      └────┘  └┘   └┘   └┘
par      └────┘  └┘   └┘   └┘
pid             └┘   └┘   
st   ───────────────────────┘└┘
1055    { exact ⟨s, rfl, rfl⟩ }
id                     └─┘
src      └────┘  └┘   └┘└─┘└┘
typ      └────┘ └┘   └┘└─┘└┘
doc      └────┘  └┘   └┘   └┘
txt      └────┘  └┘   └┘   └┘
par      └────┘  └┘   └┘   └┘
pid             └┘   └┘   
st   ───────────────────────┘└─
1056  end
st   ──┘
1057  
1058  theorem lift_rel_map {δ} (R : α → β → Prop) (S : γ → δ → Prop)
id                                                     
typ                                                    
1059    {s1 : wseq α} {s2 : wseq β}
id           └──┘         └──┘ 
src          └──┘          └──┘
typ          └──┘         └──┘ 
doc          └──┘          └──┘
1060    {f1 : α → γ} {f2 : β → δ}
id                         
typ                        
1061    (h1 : lift_rel R s1 s2) (h2 : ∀ {a b}, R a b → S (f1 a) (f2 b))
id           └──────┘  └┘ └┘                      └┘    └┘ 
src          └──────┘
typ          └──────┘  └┘ └┘                      └┘    └┘ 
doc          └──────┘
1062    : lift_rel S (map f1 s1) (map f2 s2) :=
id       └──────┘   └─┘ └┘ └┘   └─┘ └┘ └┘
src      └──────┘    └─┘         └─┘
typ      └──────┘   └─┘ └┘ └┘   └─┘ └┘ └┘
doc      └──────┘    └─┘         └─┘
1063  ⟨λ s1 s2, ∃ s t, s1 = map f1 s ∧ s2 = map f2 t ∧ lift_rel R s t,
id      └┘ └┘     └┘  └─┘ └┘   └┘  └─┘ └┘   └──────┘   
src                     └─┘           └─┘       └──────┘
typ     └┘ └┘     └┘  └─┘ └┘   └┘  └─┘ └┘   └──────┘   
doc                        └─┘             └─┘        └──────┘
1064  ⟨s1, s2, rfl, rfl, h1⟩,
id    └┘  └┘  └─┘  └─┘  └┘
src           └─┘  └─┘
typ   └┘  └┘  └─┘  └─┘  └┘
1065  λ s1 s2 h, match s1, s2, h with ._, ._, ⟨s, t, rfl, rfl, h⟩ := begin
id     └┘ └┘         └┘  └┘                            └─┘
src                                                      └─┘
typ    └┘ └┘         └┘  └┘                            └─┘
st                                                                  └─────
1066    simp [destruct_map], apply computation.lift_rel_map _ _ (lift_rel_destruct h),
id           └──────────┘         └──────────────────────┘      └───────────────┘ 
src    └────┘└──────────┘  └────┘└──────────────────────┘└───┘ └───────────────┘ 
typ    └────┘└──────────┘  └────┘└──────────────────────┘└───┘ └───────────────┘
doc    └────┘              └────┘                        └───┘                   
txt    └────┘              └────┘                        └───┘                   
par    └────┘              └────┘                        └───┘                   
pid                                                   └───┘                   
st   ────────────────────┘└────────────────────────────────────────────────────────┘└─
1067    intros o p h,
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid          └────┘
st   ─────────────┘└─
1068    cases o with a; cases p with b; simp,
id                          
src    └────┘ └─────┘  └────┘ └─────┘  └──┘
typ    └────┘└─────┘  └────┘└─────┘  └──┘
doc    └────┘ └─────┘  └────┘ └─────┘  └──┘
txt    └────┘ └─────┘  └────┘ └─────┘  └──┘
par    └────┘ └─────┘  └────┘ └─────┘  └──┘
pid          └─────┘        └─────┘
st   ─────────────────────────────────────┘└─
1069    { cases b; cases h },
id                     
src      └────┘   └────┘ 
typ      └────┘  └────┘
doc      └────┘   └────┘ 
txt      └────┘   └────┘ 
par      └────┘   └────┘ 
pid                    
st   ───┘└───────────────┘└┘
1070    { cases a; cases h },
id                     
src      └────┘   └────┘ 
typ      └────┘  └────┘
doc      └────┘   └────┘ 
txt      └────┘   └────┘ 
par      └────┘   └────┘ 
pid                    
st   ───┘└───────────────┘└┘
1071    { cases a with a s; cases b with b t, cases h with r h,
id                                               
src      └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
typ      └────┘└───────┘  └────┘└───────┘  └────┘└───────┘
doc      └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
txt      └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
par      └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
pid            └───────┘        └───────┘        └───────┘
st   ─────────────────────────────────────┘└────────────────┘└─
1072      exact ⟨h2 r, s, rfl, t, rfl, h⟩ }
id              └┘            └─┘  
src      └────┘    └┘ └┘   └┘ └┘└─┘└┘ └┘
typ      └────┘ └┘└┘└┘   └┘└┘└─┘└┘└┘
doc      └────┘    └┘ └┘   └┘ └┘   └┘ └┘
txt      └────┘    └┘ └┘   └┘ └┘   └┘ └┘
par      └────┘    └┘ └┘   └┘ └┘   └┘ └┘
pid               └┘ └┘   └┘ └┘   └┘ 
st   ───────────────────────────────────┘└─
1073  end end⟩
st   ──┘
1074  
1075  theorem map_congr (f : α → β) {s t : wseq α} (h : s ~ t) : map f s ~ map f t :=
id                                      └──┘              └─┘    └─┘  
src                                       └──┘                 └─┘      └─┘
typ                                     └──┘              └─┘    └─┘  
doc                                       └──┘                 └─┘      └─┘
1076  lift_rel_map _ _ h (λ _ _, congr_arg _)
id   └──────────┘            └───────┘
src  └──────────┘               └───────┘
typ  └──────────┘            └───────┘
1077  
1078  @[simp] def destruct_append.aux (t : wseq α) :
id                                        └──┘ 
src                                       └──┘
typ                                       └──┘ 
doc    └──┘                               └──┘
1079    option (α × wseq α) → computation (option (α × wseq α))
id     └────┘    └──┘    └─────────┘  └────┘    └──┘ 
src    └────┘     └──┘      └─────────┘  └────┘     └──┘
typ    └────┘    └──┘    └─────────┘  └────┘    └──┘ 
doc                └──┘      └─────────┘              └──┘
1080  | none          := destruct t
id     └──┘             └──────┘ 
src    └──┘             └──────┘
typ    └──┘             └──────┘ 
doc                     └──────┘
1081  | (some (a, s)) := return (some (a, append s t))
id      └──┘         └────┘  └──┘    └────┘   
src     └──┘           └────┘  └──┘    └────┘
typ     └──┘         └────┘  └──┘    └────┘   
doc                     └────┘           └────┘
1082  
1083  theorem destruct_append (s t : wseq α) :
id                                  └──┘ 
src                                 └──┘
typ                                 └──┘ 
doc                                 └──┘
1084    destruct (append s t) = (destruct s).bind (destruct_append.aux t) :=
id     └──────┘  └────┘      └──────┘  └──┘   └─────────────────┘ 
src    └──────┘  └────┘        └──────┘   └──┘   └─────────────────┘
typ    └──────┘  └────┘      └──────┘  └──┘   └─────────────────┘ 
doc    └──────┘  └────┘         └──────┘   └──┘
1085  begin
st   └─────
1086    apply eq_of_bisim (λ c1 c2, ∃ s t, c1 = destruct (append s t) ∧
id           └─────────┘                              └────┘      
src    └────┘└─────────┘  └──────┘└──┘           └────┘  └┘
typ    └────┘└─────────┘  └──────┘└──┘           └────┘  └┘
doc    └────┘             └──────┘ └──┘             └────┘  └┘ 
txt    └────┘             └──────┘ └──┘                     └┘ 
par    └────┘             └──────┘ └──┘                     └┘ 
pid                      └──────┘ └──┘                     └┘ 
st   ──────────────────────────────────────────────────────────────────
1087      c2 = (destruct s).bind (destruct_append.aux t)) _ ⟨s, t, rfl, rfl⟩,
id             └──────┘          └─────────────────┘                 └─┘
src  ───┘    └──────┘ └─────┘ └─────────────────┘ └───┘  └┘ └┘   └┘└─┘
typ  ───┘    └──────┘ └─────┘ └─────────────────┘ └───┘ └┘└┘   └┘└─┘
doc  ───┘    └──────┘ └─────┘                     └───┘  └┘ └┘   └┘   
txt  ───┘             └─────┘                     └───┘  └┘ └┘   └┘   
par  ───┘             └─────┘                     └───┘  └┘ └┘   └┘   
pid  ───┘             └─────┘                     └───┘  └┘ └┘   └┘   
st   ─────────────────────────────────────────────────────────────────────┘└─
1088    intros c1 c2 h, rcases h with ⟨s, t, h⟩, rw [h.left, h.right],
id                            
src    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
typ    └────────────┘  └─────┘└─────────────┘  └──┘└────┘└┘└─────┘
doc    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
txt    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
par    └────────────┘  └─────┘ └─────────────┘  └──┘      └┘       
pid          └──────┘         └─────────────┘    └┘      └┘       
st   ───────────────┘└───────────────────────┘└──────────┘└───────┘└──
1089    apply s.cases_on _ (λ a s, _) (λ s, _); simp; simp,
id           └────────┘
src    └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
typ    └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
doc    └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
txt    └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
par    └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
pid                   └─┘  └───────┘  └────┘
st   ───────────────────────────────────────────────────┘└─
1090    { apply t.cases_on _ (λ b t, _) (λ t, _); simp; simp,
id             └────────┘
src      └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
typ      └────┘└────────┘└─┘  └───────┘  └────┘  └──┘  └──┘
doc      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
txt      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
par      └────┘          └─┘  └───────┘  └────┘  └──┘  └──┘
pid                     └─┘  └───────┘  └────┘
st   ───┘└────────────────────────────────────────────────┘└─
1091      { refine ⟨nil, t, _, _⟩; simp } },
id                 └─┘  
src        └─────┘ └─┘└┘ └─────┘  └───┘
typ        └─────┘ └─┘└┘└─────┘  └───┘
doc        └─────┘ └─┘└┘ └─────┘  └───┘
txt        └─────┘    └┘ └─────┘  └───┘
par        └─────┘    └┘ └─────┘  └───┘
pid                  └┘ └─────┘      
st   ─────────────────────────────────┘└──┘
1092    { exact ⟨s, t, rfl, rfl⟩ }
id                       └─┘
src      └────┘  └┘ └┘   └┘└─┘└┘
typ      └────┘ └┘└┘   └┘└─┘└┘
doc      └────┘  └┘ └┘   └┘   └┘
txt      └────┘  └┘ └┘   └┘   └┘
par      └────┘  └┘ └┘   └┘   └┘
pid             └┘ └┘   └┘   
st   ──────────────────────────┘└─
1093  end
st   ──┘
1094  
1095  @[simp] def destruct_join.aux : option (wseq α × wseq (wseq α)) → computation (option (α × wseq α))
id                                   └────┘  └──┘   └──┘  └──┘     └─────────┘  └────┘    └──┘ 
src                                  └────┘  └──┘    └──┘  └──┘       └─────────┘  └────┘     └──┘
typ                                  └────┘  └──┘   └──┘  └──┘     └─────────┘  └────┘    └──┘ 
doc    └──┘                                  └──┘     └──┘  └──┘       └─────────┘              └──┘
1096  | none          := return none
id     └──┘             └────┘ └──┘
src    └──┘             └────┘ └──┘
typ    └──┘             └────┘ └──┘
doc                     └────┘
1097  | (some (s, S)) := (destruct (append s (join S))).think
id      └──┘          └──────┘  └────┘    └──┘     └───┘
src     └──┘            └──────┘  └────┘    └──┘     └───┘
typ     └──┘          └──────┘  └────┘    └──┘     └───┘
doc                      └──────┘  └────┘    └──┘     └───┘
1098  
1099  theorem destruct_join (S : wseq (wseq α)) :
id                              └──┘  └──┘ 
src                             └──┘  └──┘
typ                             └──┘  └──┘ 
doc                             └──┘  └──┘
1100    destruct (join S) = (destruct S).bind destruct_join.aux :=
id     └──────┘  └──┘     └──────┘  └──┘  └───────────────┘
src    └──────┘  └──┘      └──────┘   └──┘  └───────────────┘
typ    └──────┘  └──┘     └──────┘  └──┘  └───────────────┘
doc    └──────┘  └──┘       └──────┘   └──┘
1101  begin
st   └─────
1102    apply eq_of_bisim (λ c1 c2, c1 = c2 ∨ ∃ S, c1 = destruct (join S) ∧
id           └─────────┘                                     └──┘    
src    └────┘└─────────┘  └──────┘    └┘            └──┘ └┘
typ    └────┘└─────────┘  └──────┘    └┘            └──┘ └┘
doc    └────┘             └──────┘       └┘             └──┘ └┘ 
txt    └────┘             └──────┘       └┘                  └┘ 
par    └────┘             └──────┘       └┘                  └┘ 
pid                      └──────┘       └┘                  └┘ 
st   ──────────────────────────────────────────────────────────────────────
1103      c2 = (destruct S).bind destruct_join.aux) _ (or.inr ⟨S, rfl, rfl⟩),
id             └──────┘         └───────────────┘     └────┘         └─┘
src  ───┘    └──────┘ └─────┘└───────────────┘└──┘ └────┘  └┘   └┘└─┘└┘
typ  ───┘    └──────┘ └─────┘└───────────────┘└──┘ └────┘ └┘   └┘└─┘└┘
doc  ───┘    └──────┘ └─────┘                 └──┘         └┘   └┘   └┘
txt  ───┘             └─────┘                 └──┘         └┘   └┘   └┘
par  ───┘             └─────┘                 └──┘         └┘   └┘   └┘
pid  ───┘             └─────┘                 └──┘         └┘   └┘   └┘
st   ─────────────────────────────────────────────────────────────────────┘└─
1104    intros c1 c2 h, exact match c1, c2, h with
id                                 └┘  └┘  
src    └────────────┘  └────┘       └┘  └┘ └─────
typ    └────────────┘  └────┘     └┘└┘└┘└┘└─────
doc    └────────────┘  └────┘       └┘  └┘ └─────
txt    └────────────┘  └────┘       └┘  └┘ └─────
par    └────────────┘  └────┘       └┘  └┘ └─────
pid          └──────┘              └┘  └┘ └─────
st   ───────────────┘└────────────────────────────
1105    | _, _, (or.inl $ eq.refl c) := by cases c.destruct; simp
id              └────┘   └─────┘                └────────┘
src  ─────────┘ └────┘ └─────┘ └───┘  └────┘└────────┘└┘└────
typ  ─────────┘ └────┘ └─────┘ └───┘  └────┘└────────┘└┘└────
doc  ─────────┘                └───┘  └────┘└────────┘└┘└────
txt  ─────────┘                └───┘  └────┘          └┘└────
par  ─────────┘                └───┘  └────┘          └┘└────
pid  ─────────┘                └───┘  └─────┘          └──────
st   ───────────────────────────────────┘└───────────────────────
1106    | _, _, or.inr ⟨S, rfl, rfl⟩ := begin
src  ─┘└──────┘        └┘   └┘   └───┘     
typ  ─┘└──────┘        └┘   └┘   └───┘     
doc  ─┘└──────┘        └┘   └┘   └───┘     
txt  ─┘└──────┘        └┘   └┘   └───┘     
par  ─┘└──────┘        └┘   └┘   └───┘     
pid  ─────────┘        └┘   └┘   └───┘     
st   ─┘└──────────────────────────────┘└─────
1107      apply S.cases_on _ (λ s S, _) (λ S, _); simp; simp,
id             └────────┘
src  ───┘└────┘└────────┘└─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ─────────┘└────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ───┘└────┘          └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ───┘└────┘          └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ─────────┘          └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ─────────┘          └─┘  └───────┘  └───────────────────
st   ─────────────────────────────────────────────────────┘└─
1108      { refine or.inr ⟨S, rfl, rfl⟩ }
id                └────┘         └─┘
src  ─────┘└─────┘└────┘  └┘   └┘└─┘└┘└─
typ  ────────────┘└────┘ └┘   └┘└─┘└───
doc  ─────┘└─────┘        └┘   └┘   └┘└─
txt  ─────┘└─────┘        └┘   └┘   └┘└─
par  ────────────┘        └┘   └┘   └───
pid  ────────────┘        └┘   └┘   └───
st   ─────────────────────────────────┘└─
1109    end end
src  ─────────┘
typ  ─────────┘
doc  ─────────┘
txt  ─────────┘
par  ─────────┘
pid  ────────┘
st   ────┘└───┘
1110  end
st   └─┘
1111  
1112  theorem lift_rel_append (R : α → β → Prop) {s1 s2 : wseq α} {t1 t2 : wseq β}
id                                                     └──┘            └──┘ 
src                                                      └──┘             └──┘
typ                                                    └──┘            └──┘ 
doc                                                      └──┘             └──┘
1113    (h1 : lift_rel R s1 t1) (h2 : lift_rel R s2 t2) :
id           └──────┘  └┘ └┘        └──────┘  └┘ └┘
src          └──────┘                └──────┘
typ          └──────┘  └┘ └┘        └──────┘  └┘ └┘
doc          └──────┘                └──────┘
1114    lift_rel R (append s1 s2) (append t1 t2) :=
id     └──────┘   └────┘ └┘ └┘   └────┘ └┘ └┘
src    └──────┘    └────┘         └────┘
typ    └──────┘   └────┘ └┘ └┘   └────┘ └┘ └┘
doc    └──────┘    └────┘         └────┘
1115  ⟨λ s t, lift_rel R s t ∨ ∃ s1 t1, s = append s1 s2 ∧ t = append t1 t2 ∧ lift_rel R s1 t1,
id         └──────┘      └┘ └┘   └────┘ └┘ └┘    └────┘ └┘ └┘  └──────┘  └┘ └┘
src          └──────┘                  └────┘           └────┘        └──────┘
typ        └──────┘      └┘ └┘   └────┘ └┘ └┘    └────┘ └┘ └┘  └──────┘  └┘ └┘
doc          └──────┘                      └────┘             └────┘         └──────┘
1116  or.inr ⟨s1, t1, rfl, rfl, h1⟩,
id   └────┘  └┘  └┘  └─┘  └─┘  └┘
src  └────┘          └─┘  └─┘
typ  └────┘  └┘  └┘  └─┘  └─┘  └┘
1117  λ s t h, match s, t, h with
id                   
typ                  
1118  | s, t, or.inl h := begin
id           └────┘
src          └────┘
typ          └────┘
st                       └─────
1119      apply computation.lift_rel.imp _ _ _ (lift_rel_destruct h),
id             └──────────────────────┘        └───────────────┘ 
src      └────┘└──────────────────────┘└─────┘ └───────────────┘ 
typ      └────┘└──────────────────────┘└─────┘ └───────────────┘
doc      └────┘                        └─────┘                   
txt      └────┘                        └─────┘                   
par      └────┘                        └─────┘                   
pid                                   └─────┘                   
st   ─────────────────────────────────────────────────────────────┘└─
1120      intros a b, apply lift_rel_o.imp_right,
id                         └──────────────────┘
src      └────────┘  └────┘└──────────────────┘
typ      └────────┘  └────┘└──────────────────┘
doc      └────────┘  └────┘
txt      └────────┘  └────┘
par      └────────┘  └────┘
pid            └──┘       
st   ─────────────┘└──────────────────────────┘└─
1121      intros s t, apply or.inl
id                         └────┘
src      └────────┘  └────┘└────┘
typ      └────────┘  └────┘└────┘
doc      └────────┘  └────┘      
txt      └────────┘  └────┘      
par      └────────┘  └────┘      
pid            └──┘             
st   ─────────────┘└──────────────
1122    end
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ─┘
st   ─┘└─┘
1123  | ._, ._, or.inr ⟨s1, t1, rfl, rfl, h⟩ := begin
id             └────┘               └─┘
src            └────┘               └─┘
typ            └────┘               └─┘
st                                             └─────
1124      simp [destruct_append],
id             └─────────────┘
src      └────┘└─────────────┘
typ      └────┘└─────────────┘
doc      └────┘               
txt      └────┘               
par      └────┘               
pid                         
st   ─────────────────────────┘└─
1125      apply computation.lift_rel_bind _ _ (lift_rel_destruct h),
id             └───────────────────────┘      └───────────────┘ 
src      └────┘└───────────────────────┘└───┘ └───────────────┘ 
typ      └────┘└───────────────────────┘└───┘ └───────────────┘
doc      └────┘                         └───┘                   
txt      └────┘                         └───┘                   
par      └────┘                         └───┘                   
pid                                    └───┘                   
st   ────────────────────────────────────────────────────────────┘└─
1126      intros o p h,
src      └──────────┘
typ      └──────────┘
doc      └──────────┘
txt      └──────────┘
par      └──────────┘
pid            └────┘
st   ───────────────┘└─
1127      cases o with a; cases p with b,
id                            
src      └────┘ └─────┘  └────┘ └─────┘
typ      └────┘└─────┘  └────┘└─────┘
doc      └────┘ └─────┘  └────┘ └─────┘
txt      └────┘ └─────┘  └────┘ └─────┘
par      └────┘ └─────┘  └────┘ └─────┘
pid            └─────┘        └─────┘
st   ─────────────────────────────────┘└─
1128      { simp, apply computation.lift_rel.imp _ _ _ (lift_rel_destruct h2),
id                     └──────────────────────┘        └───────────────┘ └┘
src        └──┘  └────┘└──────────────────────┘└─────┘ └───────────────┘  
typ        └──┘  └────┘└──────────────────────┘└─────┘ └───────────────┘└┘
doc        └──┘  └────┘                        └─────┘                    
txt        └──┘  └────┘                        └─────┘                    
par        └──┘  └────┘                        └─────┘                    
pid                                           └─────┘                    
st   ─────┘└──┘└───────────────────────────────────────────────────────────┘└─
1129        intros a b, apply lift_rel_o.imp_right,
id                           └──────────────────┘
src        └────────┘  └────┘└──────────────────┘
typ        └────────┘  └────┘└──────────────────┘
doc        └────────┘  └────┘
txt        └────────┘  └────┘
par        └────────┘  └────┘
pid              └──┘       
st   ───────────────┘└──────────────────────────┘└─
1130        intros s t, apply or.inl },
id                           └────┘
src        └────────┘  └────┘└────┘
typ        └────────┘  └────┘└────┘
doc        └────────┘  └────┘      
txt        └────────┘  └────┘      
par        └────────┘  └────┘      
pid              └──┘             
st   ───────────────┘└─────────────┘└┘
1131      { cases b; cases h },
id                       
src        └────┘   └────┘ 
typ        └────┘  └────┘
doc        └────┘   └────┘ 
txt        └────┘   └────┘ 
par        └────┘   └────┘ 
pid                      
st   ─────┘└───────────────┘└┘
1132      { cases a; cases h },
id                       
src        └────┘   └────┘ 
typ        └────┘  └────┘
doc        └────┘   └────┘ 
txt        └────┘   └────┘ 
par        └────┘   └────┘ 
pid                      
st   ─────┘└───────────────┘└┘
1133      { cases a with a s; cases b with b t, cases h with r h,
id                                                 
src        └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
typ        └────┘└───────┘  └────┘└───────┘  └────┘└───────┘
doc        └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
txt        └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
par        └────┘ └───────┘  └────┘ └───────┘  └────┘ └───────┘
pid              └───────┘        └───────┘        └───────┘
st   ───────────────────────────────────────┘└────────────────┘└─
1134        simp, exact ⟨r, or.inr ⟨s, rfl, t, rfl, h⟩⟩ }
id                        └────┘           └─┘  
src        └──┘  └────┘  └┘└────┘  └┘   └┘ └┘└─┘└┘ └─┘
typ        └──┘  └────┘ └┘└────┘ └┘   └┘└┘└─┘└┘└─┘
doc        └──┘  └────┘  └┘        └┘   └┘ └┘   └┘ └─┘
txt        └──┘  └────┘  └┘        └┘   └┘ └┘   └┘ └─┘
par        └──┘  └────┘  └┘        └┘   └┘ └┘   └┘ └─┘
pid                     └┘        └┘   └┘ └┘   └┘ └┘
st   ─────────┘└──────────────────────────────────────┘└─
1135    end
st   ────┘
1136  end⟩
1137  
1138  theorem lift_rel_join.lem (R : α → β → Prop) {S T} {U : wseq α → wseq β → Prop}
id                                                         └──┘    └──┘ 
src                                                          └──┘     └──┘
typ                                                        └──┘    └──┘ 
doc                                                          └──┘     └──┘
1139    (ST : lift_rel (lift_rel R) S T) (HU : ∀ s1 s2, (∃ s t S T,
id           └──────┘  └──────┘              └┘ └┘       
src          └──────┘  └──────┘                                 
typ          └──────┘  └──────┘              └┘ └┘       
doc          └──────┘  └──────┘
1140        s1 = append s (join S) ∧ s2 = append t (join T) ∧
id         └┘  └────┘   └──┘    └┘  └────┘   └──┘   
src            └────┘    └──┘         └────┘    └──┘    
typ        └┘  └────┘   └──┘    └┘  └────┘   └──┘   
doc             └────┘    └──┘           └────┘    └──┘
1141        lift_rel R s t ∧ lift_rel (lift_rel R) S T) → U s1 s2) {a} (ma : a ∈ destruct (join S)) :
id         └──────┘     └──────┘  └──────┘         └┘ └┘              └──────┘  └──┘ 
src        └──────┘        └──────┘  └──────┘                                 └──────┘  └──┘
typ        └──────┘     └──────┘  └──────┘         └┘ └┘              └──────┘  └──┘ 
doc        └──────┘         └──────┘  └──────┘                                  └──────┘  └──┘
1142    ∃ {b}, b ∈ destruct (join T) ∧ lift_rel_o R U a b :=
id           └──────┘  └──┘    └────────┘    
src            └──────┘  └──┘     └────────┘
typ          └──────┘  └──┘    └────────┘    
doc               └──────┘  └──┘
1143  begin
st   └─────
1144    cases exists_results_of_mem ma with n h, clear ma, revert a S T,
id           └───────────────────┘ └┘
src    └────┘└───────────────────┘  └───────┘  └──────┘  └──────────┘
typ    └────┘└───────────────────┘└┘└───────┘  └──────┘  └──────────┘
doc    └────┘                       └───────┘  └──────┘  └──────────┘
txt    └────┘                       └───────┘  └──────┘  └──────────┘
par    └────┘                       └───────┘  └──────┘  └──────────┘
pid                                └───────┘       └─┘        └────┘
st   ────────────────────────────────────────┘└────────┘└────────────┘└─
1145    apply nat.strong_induction_on n _,
id           └─────────────────────┘ 
src    └────┘└─────────────────────┘ └┘
typ    └────┘└─────────────────────┘└┘
doc    └────┘                        └┘
txt    └────┘                        └┘
par    └────┘                        └┘
pid                                 └┘
st   ──────────────────────────────────┘└─
1146    intros n IH a S T ST ra, simp [destruct_join] at ra, exact
id                                    └───────────┘
src    └─────────────────────┘  └────┘└───────────┘└─────┘  └─────
typ    └─────────────────────┘  └────┘└───────────┘└─────┘  └─────
doc    └─────────────────────┘  └────┘             └─────┘  └─────
txt    └─────────────────────┘  └────┘             └─────┘  └─────
par    └─────────────────────┘  └────┘             └─────┘  └─────
pid          └───────────────┘                   └───┘       
st   ────────────────────────┘└──────────────────────────┘└───────
1147    let ⟨o, m, k, rs1, rs2, en⟩ := of_results_bind ra,
id                   └─┘              └─────────────┘ └┘
src  ─┘     └┘ └┘ └┘   └┘   └┘  └───┘└─────────────┘  └─
typ  ─┘     └┘ └┘ └┘└─┘└┘   └┘  └───┘└─────────────┘└┘└─
doc  ─┘     └┘ └┘ └┘   └┘   └┘  └───┘                 └─
txt  ─┘     └┘ └┘ └┘   └┘   └┘  └───┘                 └─
par  ─┘     └┘ └┘ └┘   └┘   └┘  └───┘                 └─
pid  ─┘     └┘ └┘ └┘   └┘   └┘  └───┘                 └─
st   ─────────────────────────────────────────────────────
1148        ⟨p, mT, rop⟩ := computation.exists_of_lift_rel_left (lift_rel_destruct ST) rs1.mem in
id                         └─────────────────────────────────┘  └───────────────┘ └┘     └──┘
src  ─────┘  └┘  └┘   └───┘└─────────────────────────────────┘ └───────────────┘  └┘   └──┘└───
typ  ─────┘  └┘  └┘   └───┘└─────────────────────────────────┘ └───────────────┘└┘└┘   └──┘└───
doc  ─────┘  └┘  └┘   └───┘                                                       └┘       └───
txt  ─────┘  └┘  └┘   └───┘                                                       └┘       └───
par  ─────┘  └┘  └┘   └───┘                                                       └┘       └───
pid  ─────┘  └┘  └┘   └───┘                                                       └┘       └───
st   ────────────────────────────────────────────────────────────────────────────────────────────
1149    by exact match o, p, rop, rs1, rs2, mT with
id                        └─┘  └─┘  └─┘  └┘
src  ─┘  └─────┘      └┘ └┘   └┘   └┘   └┘  └─────
typ  ─┘  └─────┘     └┘└┘└─┘└┘└─┘└┘└─┘└┘└┘└─────
doc  ─┘  └─────┘      └┘ └┘   └┘   └┘   └┘  └─────
txt  ─┘  └─────┘      └┘ └┘   └┘   └┘   └┘  └─────
par  ─┘  └─────┘      └┘ └┘   └┘   └┘   └┘  └─────
pid  ─┘  └─────┘      └┘ └┘   └┘   └┘   └┘  └─────
st   ───┘└─────────────────────────────────────────
1150    | none, none, _, rs1, rs2, mT := by simp [destruct_join]; exact
id                                               └───────────┘
src  ───┘    └┘    └───┘   └┘   └┘  └──┘  └────┘└───────────┘└───────
typ  ───┘    └┘    └───┘   └┘   └┘  └──┘  └────┘└───────────┘└───────
doc  ───┘    └┘    └───┘   └┘   └┘  └──┘  └────┘             └───────
txt  ───┘    └┘    └───┘   └┘   └┘  └──┘  └────┘             └───────
par  ───┘    └┘    └───┘   └┘   └┘  └──┘  └────┘             └───────
pid  ───┘    └┘    └───┘   └┘   └┘  └──┘  └─────┘             └────────
st   ────────────────────────────────────┘└────────────────────────────
1151      ⟨none, mem_bind mT (ret_mem _), by rw eq_of_ret_mem rs2.mem; trivial⟩
id        └──┘  └──────┘ └┘  └─────┘           └───────────┘ └─────┘
src  ───┘ └──┘└┘└──────┘   └─────┘└───┘  └─┘└───────────┘└─────┘└┘└─────┘└─
typ  ───┘ └──┘└┘└──────┘└┘ └─────┘└───┘  └─┘└───────────┘└─────┘└┘└─────┘└─
doc  ───┘     └┘                  └───┘  └─┘                    └┘└─────┘└─
txt  ───┘     └┘                  └───┘  └─┘                    └┘└─────┘└─
par  ───┘     └┘                  └───┘  └─┘                    └┘└─────┘└─
pid  ───┘     └┘                  └───┘  └──┘                    └──────────
st   ─────────────────────────────────────┘└────────────────────────────────┘└─
1152    | some (s, S'), some (t, T'), ⟨st, ST'⟩, rs1, rs2, mT :=
src  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
typ  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
doc  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
txt  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
par  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
pid  ───┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └───
st   ─┘└────────────────────────────────────────────────────────
1153      by simp [destruct_append] at rs2; exact
id                └─────────────┘
src  ───┘  └────┘└─────────────┘└──────┘└───────
typ  ───┘  └────┘└─────────────┘└──────┘└───────
doc  ───┘  └────┘               └──────┘└───────
txt  ───┘  └────┘               └──────┘└───────
par  ───┘  └────┘               └──────┘└───────
pid  ───┘  └─────┘               └───────────────
st   ─────┘└─────────────────────────────────────
1154      let ⟨k1, rs3, ek⟩ := of_results_think rs2,
id                └─┘         └──────────────┘ └─┘
src  ───┘      └┘   └┘  └───┘└──────────────┘   └─
typ  ───┘      └┘└─┘└┘  └───┘└──────────────┘└─┘└─
doc  ───┘      └┘   └┘  └───┘                   └─
txt  ───┘      └┘   └┘  └───┘                   └─
par  ───┘      └┘   └┘  └───┘                   └─
pid  ───┘      └┘   └┘  └───┘                   └─
st   ───────────────────────────────────────────────
1155          ⟨o', m1, n1, rs4, rs5, ek1⟩ := of_results_bind rs3,
id                        └─┘               └─────────────┘
src  ───────┘   └┘  └┘  └┘   └┘   └┘   └───┘└─────────────┘   └─
typ  ───────┘   └┘  └┘  └┘└─┘└┘   └┘   └───┘└─────────────┘   └─
doc  ───────┘   └┘  └┘  └┘   └┘   └┘   └───┘                  └─
txt  ───────┘   └┘  └┘  └┘   └┘   └┘   └───┘                  └─
par  ───────┘   └┘  └┘  └┘   └┘   └┘   └───┘                  └─
pid  ───────┘   └┘  └┘  └┘   └┘   └┘   └───┘                  └─
st   ────────────────────────────────────────────────────────────
1156          ⟨p', mt, rop'⟩ := computation.exists_of_lift_rel_left (lift_rel_destruct st) rs4.mem in
id                             └─────────────────────────────────┘  └───────────────┘ └┘
src  ───────┘   └┘  └┘    └───┘└─────────────────────────────────┘ └───────────────┘  └┘       └───
typ  ───────┘   └┘  └┘    └───┘└─────────────────────────────────┘ └───────────────┘└┘└┘       └───
doc  ───────┘   └┘  └┘    └───┘                                                       └┘       └───
txt  ───────┘   └┘  └┘    └───┘                                                       └┘       └───
par  ───────┘   └┘  └┘    └───┘                                                       └┘       └───
pid  ───────┘   └┘  └┘    └───┘                                                       └┘       └───
st   ────────────────────────────────────────────────────────────────────────────────────────────────
1157      by exact match o', p', rop', rs4, rs5, mt with
id                      └┘  └┘  └──┘  └─┘  └─┘  └┘
src  ───┘  └─────┘       └┘  └┘    └┘   └┘   └┘└┘└─────
typ  ───┘  └─────┘     └┘└┘└┘└┘└──┘└┘└─┘└┘└─┘└┘└┘└─────
doc  ───┘  └─────┘       └┘  └┘    └┘   └┘   └┘  └─────
txt  ───┘  └─────┘       └┘  └┘    └┘   └┘   └┘  └─────
par  ───┘  └─────┘       └┘  └┘    └┘   └┘   └┘  └─────
pid  ───┘  └─────┘       └┘  └┘    └┘   └┘   └┘  └─────
st   ─────┘└────────────────────────────────────────────
1158      | none, none, _, rs4, rs5', mt :=
id                             └──┘
src  ─────┘    └┘    └───┘   └┘    └┘  └───
typ  ─────┘    └┘    └───┘   └┘└──┘└┘  └───
doc  ─────┘    └┘    └───┘   └┘    └┘  └───
txt  ─────┘    └┘    └───┘   └┘    └┘  └───
par  ─────┘    └┘    └───┘   └┘    └┘  └───
pid  ─────┘    └┘    └───┘   └┘    └┘  └───
st   ──────────────────────────────────────
1159        have n1 < n, begin
id                  
src  ─────┘    └──┘ └───────
typ  ─────┘    └──┘└───────
doc  ─────┘    └──┘  └───────
txt  ─────┘    └──┘  └───────
par  ─────┘    └──┘  └───────
pid  ─────┘    └──┘  └───────
st   ───────────────────────┘
1160          rw [en, ek, ek1],
id               └┘  └┘  └─┘
src  ───────┘└──┘  └┘  └┘   └─
typ  ───────┘└──┘└┘└┘└┘└┘└─┘└─
doc  ───────┘└──┘  └┘  └┘   └─
txt  ───────┘└──┘  └┘  └┘   └─
par  ───────┘└──┘  └┘  └┘   └─
pid  ───────────┘  └┘  └┘   └──
st   ─────────────┘└──┘└───┘└──
1161          apply lt_of_lt_of_le _ (nat.le_add_right _ _),
id                 └────────────┘    └──────────────┘
src  ───────┘└────┘└────────────┘└─┘ └──────────────┘└───┘└─
typ  ─────────────┘└────────────┘└─┘ └──────────────┘└──────
doc  ───────┘└────┘              └─┘                 └───┘└─
txt  ───────┘└────┘              └─┘                 └───┘└─
par  ─────────────┘              └─┘                 └──────
pid  ─────────────┘              └─┘                 └──────
st   ────────────────────────────────────────────────────┘└─
1162          apply nat.lt_succ_of_le (nat.le_add_right _ _)
id                 └───────────────┘  └──────────────┘
src  ───────┘└────┘└───────────────┘ └──────────────┘└─────
typ  ─────────────┘└───────────────┘ └──────────────┘└─────
doc  ───────┘└────┘                                  └─────
txt  ───────┘└────┘                                  └─────
par  ─────────────┘                                  └─────
pid  ─────────────┘                                  └─────
st   ───────────────────────────────────────────────────────
1163        end,
src  ─────┘└────
typ  ───────────
doc  ─────┘└────
txt  ─────┘└────
par  ───────────
pid  ───────────
st   ─────┘└─┘└─
1164        let ⟨ob, mb, rob⟩ := IH _ this ST' rs5' in by refine ⟨ob, _, rob⟩;
id                              └┘        └─┘                    └┘     └─┘
src  ─────┘      └┘  └┘   └───┘  └─┘           └──┘  └─────┘   └───┘   └─
typ  ─────┘      └┘  └┘   └───┘└┘└─┘    └─┘    └──┘  └──────┘ └┘└───┘└─┘└──
doc  ─────┘      └┘  └┘   └───┘  └─┘           └──┘  └─────┘   └───┘   └─
txt  ─────┘      └┘  └┘   └───┘  └─┘           └──┘  └─────┘   └───┘   └─
par  ─────┘      └┘  └┘   └───┘  └─┘           └──┘  └──────┘   └───┘   └──
pid  ─────┘      └┘  └┘   └───┘  └─┘           └──┘  └──────┘   └───┘   └──
st   ──────────────────────────────────────────────────┘└─────────────────────
1165        { simp [destruct_join], apply mem_bind mT, simp [destruct_append],
id                 └───────────┘         └──────┘ └┘        └─────────────┘
src  ───────┘└────┘└───────────┘└┘└────┘└──────┘  └┘└────┘└─────────────┘└─
typ  ───────┘└────┘└───────────┘└──────┘└──────┘└┘└┘└────┘└─────────────┘└─
doc  ───────┘└────┘             └┘└────┘          └┘└────┘               └─
txt  ───────┘└────┘             └┘└────┘          └┘└────┘               └─
par  ───────┘└────┘             └──────┘          └┘└────┘               └─
pid  ─────────────┘             └───────┘          └──────┘               └──
st   ──────┘└───────────────────┘└─────────────────┘└──────────────────────┘└─
1166          apply think_mem, apply mem_bind mt, exact mb }
id                 └───────┘        └──────┘ └┘        └┘
src  ───────┘└────┘└───────┘└┘└────┘└──────┘└┘└──────┘  └──
typ  ─────────────┘└───────┘└──────┘└──────┘└┘└──────┘└┘└──
doc  ───────┘└────┘         └┘└────┘          └──────┘  └──
txt  ───────┘└────┘         └┘└────┘          └──────┘  └──
par  ─────────────┘         └──────┘          └──────┘  └──
pid  ─────────────┘         └──────┘          └──────┘  └──
st   ──────────────────────┘└─────────────────┘└─────────┘
1167      | some (a, s'), some (b, t'), ⟨ab, st'⟩, rs4, rs5, mt := begin
src  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
typ  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
doc  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
txt  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
par  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
pid  ─────┘      └┘  └─┘      └┘  └─┘   └┘   └─┘   └┘   └┘  └──┘     
st   ────────────────────────────────────────────────────────────┘└─────
1168        simp at rs5,
src  ─────┘└─────────┘└─
typ  ─────┘└─────────┘└─
doc  ─────┘└─────────┘└─
txt  ─────┘└─────────┘└─
par  ─────┘└─────────┘└─
pid  ───────────────────
st   ────────────────┘└─
1169        refine ⟨some (b, append t' (join T')), _, _⟩,
id                 └──┘    └────┘ └┘  └──┘ └┘
src  ─────┘└─────┘ └──┘  └┘└────┘   └──┘  └───────┘└─
typ  ────────────┘ └──┘ └┘└────┘└┘ └──┘└┘└──────────
doc  ─────┘└─────┘       └┘└────┘   └──┘  └───────┘└─
txt  ─────┘└─────┘       └┘               └───────┘└─
par  ────────────┘       └┘               └──────────
pid  ────────────┘       └┘               └──────────
st   ─────────────────────────────────────────────────┘└─
1170        { simp [destruct_join], apply mem_bind mT, simp [destruct_append],
id                 └───────────┘         └──────┘ └┘        └─────────────┘
src  ───────┘└────┘└───────────┘└┘└────┘└──────┘  └┘└────┘└─────────────┘└─
typ  ───────┘└────┘└───────────┘└──────┘└──────┘└┘└┘└────┘└─────────────┘└─
doc  ───────┘└────┘             └┘└────┘          └┘└────┘               └─
txt  ───────┘└────┘             └┘└────┘          └┘└────┘               └─
par  ───────┘└────┘             └──────┘          └┘└────┘               └─
pid  ─────────────┘             └───────┘          └──────┘               └──
st   ──────┘└───────────────────┘└─────────────────┘└──────────────────────┘└─
1171          apply think_mem, apply mem_bind mt, apply ret_mem },
id                 └───────┘        └──────┘ └┘        └─────┘
src  ───────┘└────┘└───────┘└┘└────┘└──────┘└┘└┘└────┘└─────┘└──
typ  ─────────────┘└───────┘└──────┘└──────┘└┘└──────┘└─────┘└───
doc  ───────┘└────┘         └┘└────┘          └┘└────┘       └──
txt  ───────┘└────┘         └┘└────┘          └┘└────┘       └──
par  ─────────────┘         └──────┘          └──────┘       └───
pid  ─────────────┘         └──────┘          └──────┘       └───
st   ──────────────────────┘└─────────────────┘└──────────────┘└─
1172        rw eq_of_ret_mem rs5.mem,
id            └───────────┘ └─────┘
src  ─────┘└─┘└───────────┘└─────┘└─
typ  ─────┘└─┘└───────────┘└─────┘└─
doc  ─────┘└─┘                    └─
txt  ─────┘└─┘                    └─
par  ─────┘└─┘                    └─
pid  ────────┘                    └─
st   ─────────────────────────────┘└─
1173        exact ⟨ab, HU _ _ ⟨s', t', S', T', rfl, rfl, st', ST'⟩⟩
id                └┘  └┘      └┘  └┘  └┘  └┘       └─┘  └─┘  └─┘
src  ───────────┘   └┘  └───┘   └┘  └┘  └┘  └┘   └┘└─┘└┘   └┘   └──
typ  ───────────┘ └┘└┘└┘└───┘ └┘└┘└┘└┘└┘└┘└┘└┘   └┘└─┘└┘└─┘└┘└─┘└──
doc  ───────────┘   └┘  └───┘   └┘  └┘  └┘  └┘   └┘   └┘   └┘   └──
txt  ───────────┘   └┘  └───┘   └┘  └┘  └┘  └┘   └┘   └┘   └┘   └──
par  ───────────┘   └┘  └───┘   └┘  └┘  └┘  └┘   └┘   └┘   └┘   └──
pid  ───────────┘   └┘  └───┘   └┘  └┘  └┘  └┘   └┘   └┘   └┘   └──
st   ──────────────────────────────────────────────────────────────
1174      end end
src  ────────────
typ  ────────────
doc  ────────────
txt  ────────────
par  ────────────
pid  ────────────
st   ───┘└─┘└────
1175    end
src  ─────┘
typ  ─────┘
doc  ─────┘
txt  ─────┘
par  ─────┘
pid  ─────┘
st   ─┘└──┘
1176  end
st   └─┘
1177  
1178  theorem lift_rel_join (R : α → β → Prop) {S : wseq (wseq α)} {T : wseq (wseq β)}
id                                               └──┘  └──┘         └──┘  └──┘ 
src                                                └──┘  └──┘          └──┘  └──┘
typ                                              └──┘  └──┘         └──┘  └──┘ 
doc                                                └──┘  └──┘          └──┘  └──┘
1179    (h : lift_rel (lift_rel R) S T) : lift_rel R (join S) (join T) :=
id          └──────┘  └──────┘        └──────┘   └──┘    └──┘ 
src         └──────┘  └──────┘           └──────┘    └──┘     └──┘
typ         └──────┘  └──────┘        └──────┘   └──┘    └──┘ 
doc         └──────┘  └──────┘           └──────┘    └──┘     └──┘
1180  ⟨λ s1 s2, ∃ s t S T,
id      └┘ └┘      
src                    
typ     └┘ └┘      
1181    s1 = append s (join S) ∧ s2 = append t (join T) ∧
id     └┘  └────┘   └──┘    └┘  └────┘   └──┘   
src        └────┘    └──┘         └────┘    └──┘    
typ    └┘  └────┘   └──┘    └┘  └────┘   └──┘   
doc         └────┘    └──┘           └────┘    └──┘
1182    lift_rel R s t ∧ lift_rel (lift_rel R) S T,
id     └──────┘     └──────┘  └──────┘    
src    └──────┘        └──────┘  └──────┘
typ    └──────┘     └──────┘  └──────┘    
doc    └──────┘         └──────┘  └──────┘
1183    ⟨nil, nil, S, T, by simp, by simp, by simp, h⟩,
id      └─┘  └─┘                                 
src     └─┘  └─┘           └──┘     └──┘     └──┘
typ     └─┘  └─┘         └──┘     └──┘     └──┘  
doc     └─┘  └─┘           └──┘     └──┘     └──┘
txt                        └──┘     └──┘     └──┘
par                        └──┘     └──┘     └──┘
st                        └───┘    └───┘    └───┘
1184  λs1 s2 ⟨s, t, S, T, h1, h2, st, ST⟩, begin
id    └┘ └┘ 
typ   └┘ └┘ 
st                                        └─────
1185    clear _fun_match _x,
src    └─────────────────┘
typ    └─────────────────┘
doc    └─────────────────┘
txt    └─────────────────┘
par    └─────────────────┘
pid         └────────────┘
st   ────────────────────┘└─
1186    rw [h1, h2], rw [destruct_append, destruct_append],
id         └┘  └┘       └─────────────┘  └─────────────┘
src    └──┘  └┘    └──┘└─────────────┘└┘└─────────────┘
typ    └──┘└┘└┘└┘  └──┘└─────────────┘└┘└─────────────┘
doc    └──┘  └┘    └──┘               └┘               
txt    └──┘  └┘    └──┘               └┘               
par    └──┘  └┘    └──┘               └┘               
pid      └┘  └┘      └┘               └┘               
st   ───────┘└──┘└────────────────────┘└───────────────┘└──
1187    apply computation.lift_rel_bind _ _ (lift_rel_destruct st),
id           └───────────────────────┘      └───────────────┘ └┘
src    └────┘└───────────────────────┘└───┘ └───────────────┘  
typ    └────┘└───────────────────────┘└───┘ └───────────────┘└┘
doc    └────┘                         └───┘                    
txt    └────┘                         └───┘                    
par    └────┘                         └───┘                    
pid                                  └───┘                    
st   ───────────────────────────────────────────────────────────┘└─
1188    exact λ o p h, match o, p, h with
src    └────┘ └──────┘      └┘ └┘ └─────
typ    └────┘ └──────┘      └┘ └┘ └─────
doc    └────┘ └──────┘      └┘ └┘ └─────
txt    └────┘ └──────┘      └┘ └┘ └─────
par    └────┘ └──────┘      └┘ └┘ └─────
pid          └──────┘      └┘ └┘ └─────
st   ────────────────────────────────────
1189    | some (a, s), some (b, t), ⟨h1, h2⟩ :=
id            
src  ───┘     └┘ └─┘      └┘ └─┘   └┘  └────
typ  ───┘     └┘ └─┘      └┘ └─┘   └┘  └────
doc  ───┘      └┘ └─┘      └┘ └─┘   └┘  └────
txt  ───┘      └┘ └─┘      └┘ └─┘   └┘  └────
par  ───┘      └┘ └─┘      └┘ └─┘   └┘  └────
pid  ───┘      └┘ └─┘      └┘ └─┘   └┘  └────
st   ──────────────────────────────────────────
1190      by simp; exact ⟨h1, s, t, S, rfl, T, rfl, h2, ST⟩
id                       └┘               └─┘  └┘  └┘
src  ───┘  └──┘└──────┘   └┘ └┘ └┘ └┘   └┘ └┘└─┘└┘  └┘  └─
typ  ───┘  └──┘└──────┘ └┘└┘└┘└┘└┘   └┘└┘└─┘└┘└┘└┘└┘└─
doc  ───┘  └──┘└──────┘   └┘ └┘ └┘ └┘   └┘ └┘   └┘  └┘  └─
txt  ───┘  └──┘└──────┘   └┘ └┘ └┘ └┘   └┘ └┘   └┘  └┘  └─
par  ───┘  └──┘└──────┘   └┘ └┘ └┘ └┘   └┘ └┘   └┘  └┘  └─
pid  ───┘  └───────────┘   └┘ └┘ └┘ └┘   └┘ └┘   └┘  └┘  └─
st   ─────┘└───────────────────────────────────────────────
1191    | none, none, _ := begin
src  ───┘    └┘    └─────┘     
typ  ───┘    └┘    └─────┘     
doc  ───┘    └┘    └─────┘     
txt  ───┘    └┘    └─────┘     
par  ───┘    └┘    └─────┘     
pid  ───┘    └┘    └─────┘     
st   ─┘└─────────────────┘└─────
1192      dsimp [destruct_append.aux, computation.lift_rel], constructor,
id              └─────────────────┘  └──────────────────┘
src  ───┘└─────┘└─────────────────┘└┘└──────────────────┘└┘└─────────┘└─
typ  ───┘└─────┘└─────────────────┘└┘└──────────────────┘└┘└─────────┘└─
doc  ───┘└─────┘                   └┘└──────────────────┘└┘└─────────┘└─
txt  ───┘└─────┘                   └┘                    └┘└─────────┘└─
par  ───┘└─────┘                   └┘                    └┘└─────────┘└─
pid  ──────────┘                   └┘                    └───────────────
st   ────────────────────────────────────────────────────┘└───────────┘└─
1193      { intro, apply lift_rel_join.lem _ ST (λ _ _, id) },
id                      └───────────────┘   └┘         └┘
src  ─────┘└───┘└┘└────┘└───────────────┘└─┘    └────┘└┘└┘└──
typ  ─────┘└───┘└──────┘└───────────────┘└─┘└┘  └────┘└┘└────
doc  ─────┘└───┘└┘└────┘                 └─┘    └────┘  └┘└──
txt  ─────┘└───┘└┘└────┘                 └─┘    └────┘  └┘└──
par  ─────┘└───┘└──────┘                 └─┘    └────┘  └────
pid  ──────────────────┘                 └─┘    └────┘  └────
st   ────┘└────┘└─────────────────────────────────────────┘└─
1194      { intros b mb,
src  ─────┘└─────────┘└─
typ  ─────┘└─────────┘└─
doc  ─────┘└─────────┘└─
txt  ─────┘└─────────┘└─
par  ─────┘└─────────┘└─
pid  ───────────────────
st   ────────────────┘└─
1195        rw [←lift_rel_o.swap], apply lift_rel_join.lem (function.swap R),
id              └─────────────┘         └───────────────┘  └───────────┘ 
src  ─────┘└───┘└─────────────┘└┘└────┘└───────────────┘ └───────────┘ └─
typ  ─────┘└───┘└─────────────┘└──────┘└───────────────┘ └───────────┘└──
doc  ─────┘└───┘               └┘└────┘                                └─
txt  ─────┘└───┘               └┘└────┘                                └─
par  ─────┘└───┘               └──────┘                                └──
pid  ──────────┘               └───────┘                                └──
st   ─────────────────────────┘└──────────────────────────────────────────┘└─
1196        { rw [←lift_rel.swap R, ←lift_rel.swap], apply ST },
id                └───────────┘    └───────────┘
src  ───────┘└───┘└───────────┘ └─┘└───────────┘└┘└────┘  └──
typ  ───────┘└───┘└───────────┘└─┘└───────────┘└──────┘  └───
doc  ───────┘└───┘              └─┘             └┘└────┘  └──
txt  ───────┘└───┘              └─┘             └┘└────┘  └──
par  ───────┘└───┘              └─┘             └──────┘  └───
pid  ────────────┘              └─┘             └───────┘  └───
st   ──────┘└───────────────────┘└──────────────┘└──────────┘└─
1197        { rw [←lift_rel.swap R, ←lift_rel.swap (lift_rel R)],
id                └───────────┘    └───────────┘  └──────┘ 
src  ───────┘└───┘└───────────┘ └─┘└───────────┘ └──────┘ └┘└─
typ  ───────┘└───┘└───────────┘└─┘└───────────┘ └──────┘└┘└─
doc  ───────┘└───┘              └─┘              └──────┘ └┘└─
txt  ───────┘└───┘              └─┘                       └┘└─
par  ───────┘└───┘              └─┘                       └┘└─
pid  ────────────┘              └─┘                       └───
st   ──────┘└───────────────────┘└───────────────────────────┘└──
1198          exact λ s1 s2 ⟨s, t, S, T, h1, h2, st, ST⟩,
id                                  └┘  └┘  └┘  └┘
src  ─────────────┘ └──────┘ └┘ └┘ └┘ └┘  └┘  └┘  └┘  └──
typ  ─────────────┘ └──────┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└┘└──
doc  ─────────────┘ └──────┘ └┘ └┘ └┘ └┘  └┘  └┘  └┘  └──
txt  ─────────────┘ └──────┘ └┘ └┘ └┘ └┘  └┘  └┘  └┘  └──
par  ─────────────┘ └──────┘ └┘ └┘ └┘ └┘  └┘  └┘  └┘  └──
pid  ─────────────┘ └──────┘ └┘ └┘ └┘ └┘  └┘  └┘  └┘  └──
st   ────────────────────────────────────────────────────
1199                        ⟨t, s, T, S, h2, h1, st, ST⟩ },
src  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
typ  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
doc  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
txt  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
par  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
pid  ─────────────────────┘  └┘ └┘ └┘ └┘  └┘  └┘  └┘  └────
st   ──────────────────────────────────────────────────┘└─
1200        { exact mb } }
id                 └┘
src  ─────────────┘  └────
typ  ─────────────┘└┘└────
doc  ─────────────┘  └────
txt  ─────────────┘  └────
par  ─────────────┘  └────
pid  ─────────────┘  └────
st   ────────────────┘└───
1201    end end
src  ─────────┘
typ  ─────────┘
doc  ─────────┘
txt  ─────────┘
par  ─────────┘
pid  ────────┘
st   ────┘└───┘
1202  end⟩
st   └─┘
1203  
1204  theorem join_congr {S T : wseq (wseq α)} (h : lift_rel equiv S T) : join S ~ join T :=
id                             └──┘  └──┘         └──────┘ └───┘      └──┘   └──┘ 
src                            └──┘  └──┘          └──────┘ └───┘        └──┘    └──┘
typ                            └──┘  └──┘         └──────┘ └───┘      └──┘   └──┘ 
doc                            └──┘  └──┘          └──────┘ └───┘        └──┘    └──┘
1205  lift_rel_join _ h
id   └───────────┘   
src  └───────────┘
typ  └───────────┘   
1206  
1207  theorem lift_rel_bind {δ} (R : α → β → Prop) (S : γ → δ → Prop)
id                                                      
typ                                                     
1208    {s1 : wseq α} {s2 : wseq β}
id           └──┘         └──┘ 
src          └──┘          └──┘
typ          └──┘         └──┘ 
doc          └──┘          └──┘
1209    {f1 : α → wseq γ} {f2 : β → wseq δ}
id              └──┘            └──┘ 
src              └──┘              └──┘
typ             └──┘            └──┘ 
doc              └──┘              └──┘
1210    (h1 : lift_rel R s1 s2) (h2 : ∀ {a b}, R a b → lift_rel S (f1 a) (f2 b))
id           └──────┘  └┘ └┘                    └──────┘   └┘    └┘ 
src          └──────┘                                 └──────┘
typ          └──────┘  └┘ └┘                    └──────┘   └┘    └┘ 
doc          └──────┘                                 └──────┘
1211    : lift_rel S (bind s1 f1) (bind s2 f2) :=
id       └──────┘   └──┘ └┘ └┘   └──┘ └┘ └┘
src      └──────┘    └──┘         └──┘
typ      └──────┘   └──┘ └┘ └┘   └──┘ └┘ └┘
doc      └──────┘    └──┘         └──┘
1212  lift_rel_join _ (lift_rel_map _ _ h1 @h2)
id   └───────────┘    └──────────┘     └┘  └┘
src  └───────────┘    └──────────┘
typ  └───────────┘    └──────────┘     └┘  └┘
1213  
1214  theorem bind_congr {s1 s2 : wseq α} {f1 f2 : α → wseq β}
id                               └──┘               └──┘ 
src                              └──┘                 └──┘
typ                              └──┘               └──┘ 
doc                              └──┘                 └──┘
1215    (h1 : s1 ~ s2) (h2 : ∀ a, f1 a ~ f2 a) : bind s1 f1 ~ bind s2 f2 :=
id           └┘  └┘            └┘   └┘     └──┘ └┘ └┘  └──┘ └┘ └┘
src                                           └──┘        └──┘
typ          └┘  └┘            └┘   └┘     └──┘ └┘ └┘  └──┘ └┘ └┘
doc                                           └──┘        └──┘
1216  lift_rel_bind _ _ h1 (λ a b h, by rw h; apply h2)
id   └───────────┘     └┘              
src  └───────────┘                     └─┘   └────┘
typ  └───────────┘     └┘           └─┘  └────┘
doc                                    └─┘   └────┘
txt                                    └─┘   └────┘
par                                    └─┘   └────┘
pid                                              
st                                    └─────────────┘
1217  
1218  @[simp] theorem join_ret (s : wseq α) : join (ret s) ~ s :=
id                                 └──┘     └──┘  └─┘    
src                                └──┘      └──┘  └─┘    
typ                                └──┘     └──┘  └─┘    
doc    └──┘                        └──┘      └──┘  └─┘    
1219  by simp [ret]; apply think_equiv
id            └─┘         └─────────┘
src     └────┘└─┘  └────┘└─────────┘
typ     └────┘└─┘  └────┘└─────────┘
doc     └────┘└─┘  └────┘           
txt     └────┘     └────┘           
par     └────┘     └────┘           
pid                              
st     └──────────────────────────────
1220  
src  
typ  
doc  
txt  
par  
pid  
st   
1221  @[simp] theorem join_map_ret (s : wseq α) : join (map ret s) ~ s :=
id                                     └──┘     └──┘  └─┘ └─┘    
src                                    └──┘      └──┘  └─┘ └─┘    
typ                                    └──┘     └──┘  └─┘ └─┘    
doc    └──┘                            └──┘      └──┘  └─┘ └─┘    
1222  begin
st   └─────
1223    refine ⟨λ s1 s2, join (map ret s2) = s1, rfl, _⟩,
id                      └──┘  └─┘ └─┘          └─┘
src    └─────┘  └──────┘└──┘ └─┘└─┘  └┘  └┘└─┘└──┘
typ    └─────┘  └──────┘└──┘ └─┘└─┘  └┘  └┘└─┘└──┘
doc    └─────┘  └──────┘└──┘ └─┘└─┘  └┘   └┘   └──┘
txt    └─────┘  └──────┘             └┘   └┘   └──┘
par    └─────┘  └──────┘             └┘   └┘   └──┘
pid            └──────┘             └┘   └┘   └──┘
st   ─────────────────────────────────────────────────┘└─
1224    intros s' s h, rw ←h,
id                        
src    └───────────┘  └──┘
typ    └───────────┘  └──┘
doc    └───────────┘  └──┘
txt    └───────────┘  └──┘
par    └───────────┘  └──┘
pid          └─────┘    └┘
st   ──────────────┘└─────┘└─
1225    apply lift_rel_rec
id           └──────────┘
src    └────┘└──────────┘
typ    └────┘└──────────┘
doc    └────┘            
txt    └────┘            
par    └────┘            
pid                     
st   ─────────────────────
1226      (λ c1 c2, ∃ s,
id                   
src  ───┘  └──────┘└┘
typ  ───┘  └──────┘└┘
doc  ───┘  └──────┘ └┘ 
txt  ───┘  └──────┘ └┘ 
par  ───┘  └──────┘ └┘ 
pid  ───┘  └──────┘ └┘ 
st   ───────────────────
1227        c1 = destruct (join (map ret s)) ∧ c2 = destruct s),
id                        └──┘  └─┘ └─┘            └──────┘
src  ─────┘            └──┘ └─┘└─┘ └─┘    └──────┘ 
typ  ─────┘            └──┘ └─┘└─┘ └─┘    └──────┘ 
doc  ─────┘            └──┘ └─┘└─┘ └─┘    └──────┘ 
txt  ─────┘                        └─┘             
par  ─────┘                        └─┘             
pid  ─────┘                        └─┘             
st   ────────────────────────────────────────────────────────┘└─
1228    { exact λ c1 c2 h, match c1, c2, h with
src      └────┘ └────────┘       └┘  └┘ └─────
typ      └────┘ └────────┘       └┘  └┘ └─────
doc      └────┘ └────────┘       └┘  └┘ └─────
txt      └────┘ └────────┘       └┘  └┘ └─────
par      └────┘ └────────┘       └┘  └┘ └─────
pid            └────────┘       └┘  └┘ └─────
st   ───┘└─────────────────────────────────────
1229      | ._, ._, ⟨s, rfl, rfl⟩ := begin
src  ─────┘  └┘  └┘  └┘   └┘   └───┘     
typ  ─────┘  └┘  └┘  └┘   └┘   └───┘     
doc  ─────┘  └┘  └┘  └┘   └┘   └───┘     
txt  ─────┘  └┘  └┘  └┘   └┘   └───┘     
par  ─────┘  └┘  └┘  └┘   └┘   └───┘     
pid  ─────┘  └┘  └┘  └┘   └┘   └───┘     
st   ──────────────────────────────┘└─────
1230        clear h _match,
src  ─────┘└────────────┘└─
typ  ─────┘└────────────┘└─
doc  ─────┘└────────────┘└─
txt  ─────┘└────────────┘└─
par  ─────┘└────────────┘└─
pid  ──────────────────────
st   ───────────────────┘└─
1231        apply s.cases_on _ (λ a s, _) (λ s, _); simp [ret]; simp [ret],
id               └────────┘                              └─┘         └─┘
src  ─────┘└────┘└────────┘└─┘  └───────┘  └────┘└┘└────┘└─┘└┘└────┘└─┘└─
typ  ───────────┘└────────┘└─┘  └───────┘  └──────┘└────┘└─┘└┘└────┘└─┘└─
doc  ─────┘└────┘          └─┘  └───────┘  └────┘└┘└────┘└─┘└┘└────┘└─┘└─
txt  ─────┘└────┘          └─┘  └───────┘  └────┘└┘└────┘   └┘└────┘   └─
par  ───────────┘          └─┘  └───────┘  └──────┘└────┘   └┘└────┘   └─
pid  ───────────┘          └─┘  └───────┘  └────────────┘   └───────┘   └──
st   ───────────────────────────────────────────────────────────────────┘└─
1232        { refine ⟨_, ret_mem _, _⟩, simp },
id                      └─────┘
src  ───────┘└─────┘ └─┘└─────┘└────┘└┘└───┘└──
typ  ──────────────┘ └─┘└─────┘└──────┘└───┘└──
doc  ───────┘└─────┘ └─┘       └────┘└┘└───┘└──
txt  ───────┘└─────┘ └─┘       └────┘└┘└───┘└──
par  ──────────────┘ └─┘       └──────┘└───┘└──
pid  ──────────────┘ └─┘       └───────────────
st   ──────┘└───────────────────────┘└─────┘└─
1233        { exact ⟨s, rfl, rfl⟩ }
id                         └─┘
src  ─────────────┘  └┘   └┘└─┘└───
typ  ─────────────┘ └┘   └┘└─┘└───
doc  ─────────────┘  └┘   └┘   └───
txt  ─────────────┘  └┘   └┘   └───
par  ─────────────┘  └┘   └┘   └───
pid  ─────────────┘  └┘   └┘   └───
st   ───────────────────────────┘└─
1234      end end },
src  ───────────┘
typ  ───────────┘
doc  ───────────┘
txt  ───────────┘
par  ───────────┘
pid  ──────────┘
st   ──────┘└───┘└┘
1235    { exact ⟨s, rfl, rfl⟩ }
id                     └─┘
src      └────┘  └┘   └┘└─┘└┘
typ      └────┘ └┘   └┘└─┘└┘
doc      └────┘  └┘   └┘   └┘
txt      └────┘  └┘   └┘   └┘
par      └────┘  └┘   └┘   └┘
pid             └┘   └┘   
st   ───────────────────────┘└─
1236  end
st   ──┘
1237  
1238  @[simp] theorem join_append (S T : wseq (wseq α)) :
id                                      └──┘  └──┘ 
src                                     └──┘  └──┘
typ                                     └──┘  └──┘ 
doc    └──┘                             └──┘  └──┘
1239    join (append S T) ~ append (join S) (join T) :=
id     └──┘  └────┘     └────┘  └──┘    └──┘ 
src    └──┘  └────┘       └────┘  └──┘     └──┘
typ    └──┘  └────┘     └────┘  └──┘    └──┘ 
doc    └──┘  └────┘       └────┘  └──┘     └──┘
1240  begin
st   └─────
1241    refine ⟨λ s1 s2, ∃ s S T,
id                            
src    └─────┘  └──────┘└────┘
typ    └─────┘  └──────┘└────┘
doc    └─────┘  └──────┘ └────┘ 
txt    └─────┘  └──────┘ └────┘ 
par    └─────┘  └──────┘ └────┘ 
pid            └──────┘ └────┘ 
st   ────────────────────────────
1242      s1 = append s (join (append S T)) ∧
id                                        
src  ───┘                       └─┘
typ  ───┘                       └─┘
doc  ───┘                        └─┘ 
txt  ───┘                        └─┘ 
par  ───┘                        └─┘ 
pid  ───┘                        └─┘ 
st   ────────────────────────────────────────
1243      s2 = append s (append (join S) (join T)), ⟨nil, S, T, by simp, by simp⟩, _⟩,
id                      └────┘           └──┘       └─┘    
src  ───┘           └────┘      └┘ └──┘ └──┘ └─┘└┘ └┘ └┘  └──┘└┘  └──┘└───┘
typ  ───┘           └────┘      └┘ └──┘ └──┘ └─┘└┘└┘└┘  └──┘└┘  └──┘└───┘
doc  ───┘           └────┘      └┘ └──┘ └──┘ └─┘└┘ └┘ └┘  └──┘└┘  └──┘└───┘
txt  ───┘                       └┘      └──┘    └┘ └┘ └┘  └──┘└┘  └──┘└───┘
par  ───┘                       └┘      └──┘    └┘ └┘ └┘  └──┘└┘  └──┘└───┘
pid  ───┘                       └┘      └──┘    └┘ └┘ └┘  └─────┘  └────────┘
st   ───────────────────────────────────────────────────────────┘└───┘└──┘└───┘└───┘└─
1244    intros s1 s2 h,
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid          └──────┘
st   ───────────────┘└─
1245    apply lift_rel_rec (λ c1 c2, ∃ (s : wseq α) S T,
id           └──────────┘                 └──┘      
src    └────┘└──────────┘  └──────┘└────┘└──┘ └───┘
typ    └────┘└──────────┘  └──────┘└────┘└──┘└───┘
doc    └────┘              └──────┘ └────┘└──┘ └───┘ 
txt    └────┘              └──────┘ └────┘     └───┘ 
par    └────┘              └──────┘ └────┘     └───┘ 
pid                       └──────┘ └────┘     └───┘ 
st   ───────────────────────────────────────────────────
1246      c1 = destruct (append s (join (append S T))) ∧
src  ───┘                                 └──┘ 
typ  ───┘                                 └──┘ 
doc  ───┘                                 └──┘ 
txt  ───┘                                 └──┘ 
par  ───┘                                 └──┘ 
pid  ───┘                                 └──┘ 
st   ───────────────────────────────────────────────────
1247      c2 = destruct (append s (append (join S) (join T)))) _ _ _
id                                └────┘           └──┘
src  ───┘                    └────┘      └┘ └──┘ └──────────
typ  ───┘                    └────┘      └┘ └──┘ └──────────
doc  ───┘                    └────┘      └┘ └──┘ └──────────
txt  ───┘                                └┘      └──────────
par  ───┘                                └┘      └──────────
pid  ───┘                                └┘      └──────────
st   ───────────────────────────────────────────────────────────────
1248      (let ⟨s, S, T, h1, h2⟩ := h in
id                   └┘  └┘     
src  ───┘      └┘ └┘ └┘  └┘  └───┘ └───
typ  ───┘     └┘└┘└┘└┘└┘└┘└───┘└───
doc  ───┘      └┘ └┘ └┘  └┘  └───┘ └───
txt  ───┘      └┘ └┘ └┘  └┘  └───┘ └───
par  ───┘      └┘ └┘ └┘  └┘  └───┘ └───
pid  ───┘      └┘ └┘ └┘  └┘  └───┘ └───
st   ───────────────────────────────────
1249           ⟨s, S, T, congr_arg destruct h1, congr_arg destruct h2⟩),
id                                             └───────┘ └──────┘
src  ────────┘  └┘ └┘ └┘                   └┘└───────┘└──────┘  └┘
typ  ────────┘  └┘ └┘ └┘                   └┘└───────┘└──────┘  └┘
doc  ────────┘  └┘ └┘ └┘                   └┘         └──────┘  └┘
txt  ────────┘  └┘ └┘ └┘                   └┘                   └┘
par  ────────┘  └┘ └┘ └┘                   └┘                   └┘
pid  ────────┘  └┘ └┘ └┘                   └┘                   └┘
st   ────────────────────────────────────────────────────────────────┘└─
1250    intros c1 c2 h,
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid          └──────┘
st   ───────────────┘└─
1251    exact match c1, c2, h with ._, ._, ⟨s, S, T, rfl, rfl⟩ := begin
id                 └┘  └┘                               └─┘
src    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘ └┘   └┘└─┘└───┘     
typ    └────┘     └┘└┘└┘└┘└────┘  └┘  └┘  └┘ └┘ └┘   └┘└─┘└───┘     
doc    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘ └┘   └┘   └───┘     
txt    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘ └┘   └┘   └───┘     
par    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘ └┘   └┘   └───┘     
pid                └┘  └┘ └────┘  └┘  └┘  └┘ └┘ └┘   └┘   └───┘     
st   ───────────────────────────────────────────────────────────┘└─────
1252      clear _match h h,
src  ───┘└──────────────┘└─
typ  ───┘└──────────────┘└─
doc  ───┘└──────────────┘└─
txt  ───┘└──────────────┘└─
par  ───┘└──────────────┘└─
pid  ──────────────────────
st   ───────────────────┘└─
1253      apply wseq.cases_on s _ (λ a s, _) (λ s, _); simp; simp,
id             └───────────┘ 
src  ───┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ─────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ───┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ───┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ─────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ─────────┘              └─┘  └───────┘  └───────────────────
st   ──────────────────────────────────────────────────────────┘└─
1254      { apply wseq.cases_on S _ (λ s S, _) (λ S, _); simp; simp,
id               └───────────┘ 
src  ─────┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ───────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ───────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ───────────┘              └─┘  └───────┘  └───────────────────
st   ────┘└──────────────────────────────────────────────────────┘└─
1255        { apply wseq.cases_on T _ (λ s T, _) (λ T, _); simp; simp,
id                 └───────────┘ 
src  ───────┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ─────────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ───────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ───────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ─────────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ─────────────┘              └─┘  └───────┘  └───────────────────
st   ──────┘└──────────────────────────────────────────────────────┘└─
1256          { refine ⟨s, nil, T, _, _⟩; simp },
id                       └─┘  
src  ─────────┘└─────┘  └┘└─┘└┘ └─────┘└┘└───┘└──
typ  ────────────────┘ └┘└─┘└┘└───────┘└───┘└──
doc  ─────────┘└─────┘  └┘└─┘└┘ └─────┘└┘└───┘└──
txt  ─────────┘└─────┘  └┘   └┘ └─────┘└┘└───┘└──
par  ────────────────┘  └┘   └┘ └───────┘└───┘└──
pid  ────────────────┘  └┘   └┘ └────────────────
st   ────────┘└──────────────────────────────┘└─
1257          { refine ⟨nil, nil, T, _, _⟩; simp } },
id                          └─┘  
src  ─────────┘└─────┘    └┘└─┘└┘ └─────┘└┘└───┘└────
typ  ────────────────┘    └┘└─┘└┘└───────┘└───┘└────
doc  ─────────┘└─────┘    └┘└─┘└┘ └─────┘└┘└───┘└────
txt  ─────────┘└─────┘    └┘   └┘ └─────┘└┘└───┘└────
par  ────────────────┘    └┘   └┘ └───────┘└───┘└────
pid  ────────────────┘    └┘   └┘ └──────────────────
st   ──────────────────────────────────────────┘└─┘└─
1258        { exact ⟨s, S, T, rfl, rfl⟩ },
id                             └─┘
src  ─────────────┘  └┘ └┘ └┘   └┘└─┘└────
typ  ─────────────┘ └┘└┘└┘   └┘└─┘└────
doc  ─────────────┘  └┘ └┘ └┘   └┘   └────
txt  ─────────────┘  └┘ └┘ └┘   └┘   └────
par  ─────────────┘  └┘ └┘ └┘   └┘   └────
pid  ─────────────┘  └┘ └┘ └┘   └┘   └────
st   ──────┘└─────────────────────────┘└─
1259        { refine ⟨nil, S, T, _, _⟩; simp } },
id                   └─┘    
src  ───────┘└─────┘ └─┘└┘ └┘ └─────┘└┘└───┘└────
typ  ──────────────┘ └─┘└┘└┘└───────┘└───┘└────
doc  ───────┘└─────┘ └─┘└┘ └┘ └─────┘└┘└───┘└────
txt  ───────┘└─────┘    └┘ └┘ └─────┘└┘└───┘└────
par  ──────────────┘    └┘ └┘ └───────┘└───┘└────
pid  ──────────────┘    └┘ └┘ └──────────────────
st   ──────────────────────────────────────┘└─┘└─
1260      { exact ⟨s, S, T, rfl, rfl⟩ },
id                           └─┘
src  ───────────┘  └┘ └┘ └┘   └┘└─┘└────
typ  ───────────┘ └┘└┘└┘   └┘└─┘└────
doc  ───────────┘  └┘ └┘ └┘   └┘   └────
txt  ───────────┘  └┘ └┘ └┘   └┘   └────
par  ───────────┘  └┘ └┘ └┘   └┘   └────
pid  ───────────┘  └┘ └┘ └┘   └┘   └────
st   ────┘└─────────────────────────┘└─
1261      { exact ⟨s, S, T, rfl, rfl⟩ }
id                           └─┘
src  ───────────┘  └┘ └┘ └┘   └┘└─┘└───
typ  ───────────┘ └┘└┘└┘   └┘└─┘└───
doc  ───────────┘  └┘ └┘ └┘   └┘   └───
txt  ───────────┘  └┘ └┘ └┘   └┘   └───
par  ───────────┘  └┘ └┘ └┘   └┘   └───
pid  ───────────┘  └┘ └┘ └┘   └┘   └───
st   ───────────────────────────────┘└─
1262    end end
src  ─────────┘
typ  ─────────┘
doc  ─────────┘
txt  ─────────┘
par  ─────────┘
pid  ────────┘
st   ────┘└───┘
1263  end
st   └─┘
1264  
1265  @[simp] theorem bind_ret (f : α → β) (s) : bind s (ret ∘ f) ~ map f s :=
id                                            └──┘   └─┘     └─┘  
src                                             └──┘    └─┘      └─┘
typ                                           └──┘   └─┘     └─┘  
doc    └──┘                                     └──┘    └─┘       └─┘
1266  begin
st   └─────
1267    dsimp [bind], change (λx, ret (f x)) with (ret ∘ f),
id            └──┘               └─┘             └─┘  
src    └─────┘└──┘  └─────┘  └─┘└─┘   └──────┘ └─┘ 
typ    └─────┘└──┘  └─────┘  └─┘└─┘  └──────┘ └─┘
doc    └─────┘└──┘  └─────┘  └─┘└─┘   └──────┘ └─┘  
txt    └─────┘      └─────┘  └─┘      └──────┘      
par    └─────┘      └─────┘  └─┘      └──────┘      
pid                       └─┘      └┘└────┘      
st   ─────────────┘└────────────────────────────────────────
1268    rw [map_comp], apply join_map_ret
id         └──────┘         └──────────┘
src    └──┘└──────┘  └────┘└──────────┘
typ    └──┘└──────┘  └────┘└──────────┘
doc    └──┘          └────┘            
txt    └──┘          └────┘            
par    └──┘          └────┘            
pid      └┘                           
st   ─────────────┘└────────────────────┘
1269  end
st   └─┘
1270  
1271  @[simp] theorem ret_bind (a : α) (f : α → wseq β) :
id                                           └──┘ 
src                                            └──┘
typ                                          └──┘ 
doc    └──┘                                    └──┘
1272    bind (ret a) f ~ f a := by simp [bind]
id     └──┘  └─┘                   └──┘
src    └──┘  └─┘                 └────┘└──┘└─
typ    └──┘  └─┘             └────┘└──┘└─
doc    └──┘  └─┘                 └────┘└──┘└─
txt                               └────┘    └─
par                               └────┘    └─
pid                                       
st                               └────────────
1273  
src  
typ  
doc  
txt  
par  
pid  
st   
1274  @[simp] theorem map_join (f : α → β) (S) :
id                                    
typ                                   
doc    └──┘
1275    map f (join S) = join (map (map f) S) :=
id     └─┘   └──┘    └──┘  └─┘  └─┘   
src    └─┘    └──┘     └──┘  └─┘  └─┘
typ    └─┘   └──┘    └──┘  └─┘  └─┘   
doc    └─┘    └──┘      └──┘  └─┘  └─┘
1276  begin
st   └─────
1277    apply seq.eq_of_bisim (λs1 s2,
id           └─────────────┘
src    └────┘└─────────────┘  └──────
typ    └────┘└─────────────┘  └──────
doc    └────┘                 └──────
txt    └────┘                 └──────
par    └────┘                 └──────
pid                          └──────
st   ─────────────────────────────────
1278      ∃ s S, s1 = append s (map f (join S)) ∧
id                                          
src  ───┘└──┘                    └─┘
typ  ───┘└──┘                    └─┘
doc  ───┘ └──┘                      └─┘ 
txt  ───┘ └──┘                      └─┘ 
par  ───┘ └──┘                      └─┘ 
pid  ───┘ └──┘                      └─┘ 
st   ────────────────────────────────────────────
1279        s2 = append s (join (map (map f) S))),
id              └────┘    └──┘       └─┘ 
src  ─────┘   └────┘  └──┘     └─┘ └┘ └─┘
typ  ─────┘   └────┘  └──┘     └─┘└┘ └─┘
doc  ─────┘   └────┘  └──┘     └─┘ └┘ └─┘
txt  ─────┘                        └┘ └─┘
par  ─────┘                        └┘ └─┘
pid  ─────┘                        └┘ └─┘
st   ──────────────────────────────────────────┘└─
1280    { intros s1 s2 h,
src      └────────────┘
typ      └────────────┘
doc      └────────────┘
txt      └────────────┘
par      └────────────┘
pid            └──────┘
st   ───┘└────────────┘└─
1281      exact match s1, s2, h with ._, ._, ⟨s, S, rfl, rfl⟩ := begin
id                   └┘  └┘                            └─┘
src      └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘   └┘└─┘└───┘     
typ      └────┘     └┘└┘└┘└┘└────┘  └┘  └┘  └┘ └┘   └┘└─┘└───┘     
doc      └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘   └┘   └───┘     
txt      └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘   └┘   └───┘     
par      └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘   └┘   └───┘     
pid                  └┘  └┘ └────┘  └┘  └┘  └┘ └┘   └┘   └───┘     
st   ──────────────────────────────────────────────────────────┘└─────
1282        apply wseq.cases_on s _ (λ a s, _) (λ s, _); simp; simp,
id               └───────────┘ 
src  ─────┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ───────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ───────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ───────────┘              └─┘  └───────┘  └───────────────────
st   ────────────────────────────────────────────────────────────┘└─
1283        { apply wseq.cases_on S _ (λ s S, _) (λ S, _); simp; simp,
id                 └───────────┘ 
src  ───────┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ─────────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ───────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ───────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ─────────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ─────────────┘              └─┘  └───────┘  └───────────────────
st   ──────┘└──────────────────────────────────────────────────────┘└─
1284          { exact ⟨map f s, S, rfl, rfl⟩ },
id                    └─┘           └─┘
src  ───────────────┘ └─┘  └┘ └┘   └┘└─┘└────
typ  ───────────────┘ └─┘└┘└┘   └┘└─┘└────
doc  ───────────────┘ └─┘  └┘ └┘   └┘   └────
txt  ───────────────┘      └┘ └┘   └┘   └────
par  ───────────────┘      └┘ └┘   └┘   └────
pid  ───────────────┘      └┘ └┘   └┘   └────
st   ────────┘└────────────────────────────┘└─
1285          { refine ⟨nil, S, _, _⟩; simp } },
id                     └─┘  
src  ─────────┘└─────┘ └─┘└┘ └─────┘└┘└───┘└────
typ  ────────────────┘ └─┘└┘└───────┘└───┘└────
doc  ─────────┘└─────┘ └─┘└┘ └─────┘└┘└───┘└────
txt  ─────────┘└─────┘    └┘ └─────┘└┘└───┘└────
par  ────────────────┘    └┘ └───────┘└───┘└────
pid  ────────────────┘    └┘ └──────────────────
st   ─────────────────────────────────────┘└─┘└─
1286        { exact ⟨_, _, rfl, rfl⟩ },
id                             └─┘
src  ─────────────┘ └────┘   └┘└─┘└────
typ  ─────────────┘ └────┘   └┘└─┘└────
doc  ─────────────┘ └────┘   └┘   └────
txt  ─────────────┘ └────┘   └┘   └────
par  ─────────────┘ └────┘   └┘   └────
pid  ─────────────┘ └────┘   └┘   └────
st   ──────┘└──────────────────────┘└─
1287        { exact ⟨_, _, rfl, rfl⟩ }
id                             └─┘
src  ─────────────┘ └────┘   └┘└─┘└───
typ  ─────────────┘ └────┘   └┘└─┘└───
doc  ─────────────┘ └────┘   └┘   └───
txt  ─────────────┘ └────┘   └┘   └───
par  ─────────────┘ └────┘   └┘   └───
pid  ─────────────┘ └────┘   └┘   └───
st   ──────────────────────────────┘└─
1288      end end },
src  ───────────┘
typ  ───────────┘
doc  ───────────┘
txt  ───────────┘
par  ───────────┘
pid  ──────────┘
st   ──────┘└───┘└┘
1289    { refine ⟨nil, S, _, _⟩; simp }
id               └─┘  
src      └─────┘ └─┘└┘ └─────┘  └───┘
typ      └─────┘ └─┘└┘└─────┘  └───┘
doc      └─────┘ └─┘└┘ └─────┘  └───┘
txt      └─────┘    └┘ └─────┘  └───┘
par      └─────┘    └┘ └─────┘  └───┘
pid                └┘ └─────┘      
st   ───────────────────────────────┘└─
1290  end
st   ──┘
1291  
1292  @[simp] theorem join_join (SS : wseq (wseq (wseq α))) :
id                                   └──┘  └──┘  └──┘ 
src                                  └──┘  └──┘  └──┘
typ                                  └──┘  └──┘  └──┘ 
doc    └──┘                          └──┘  └──┘  └──┘
1293    join (join SS) ~ join (map join SS) :=
id     └──┘  └──┘ └┘   └──┘  └─┘ └──┘ └┘
src    └──┘  └──┘      └──┘  └─┘ └──┘
typ    └──┘  └──┘ └┘   └──┘  └─┘ └──┘ └┘
doc    └──┘  └──┘      └──┘  └─┘ └──┘
1294  begin
st   └─────
1295    refine ⟨λ s1 s2, ∃ s S SS,
id                             
src    └─────┘  └──────┘└─────┘
typ    └─────┘  └──────┘└─────┘
doc    └─────┘  └──────┘ └─────┘ 
txt    └─────┘  └──────┘ └─────┘ 
par    └─────┘  └──────┘ └─────┘ 
pid            └──────┘ └─────┘ 
st   ─────────────────────────────
1296      s1 = append s (join (append S (join SS))) ∧
id                                                
src  ───┘                             └──┘
typ  ───┘                             └──┘
doc  ───┘                              └──┘ 
txt  ───┘                              └──┘ 
par  ───┘                              └──┘ 
pid  ───┘                              └──┘ 
st   ────────────────────────────────────────────────
1297      s2 = append s (append (join S) (join (map join SS))),
id                      └────┘                 └─┘ └──┘
src  ───┘           └────┘      └┘      └─┘└──┘  └────
typ  ───┘           └────┘      └┘      └─┘└──┘  └────
doc  ───┘           └────┘      └┘      └─┘└──┘  └────
txt  ───┘                       └┘               └────
par  ───┘                       └┘               └────
pid  ───┘                       └┘               └────
st   ──────────────────────────────────────────────────────────
1298      ⟨nil, nil, SS, by simp, by simp⟩, _⟩,
id             └─┘  └┘
src  ───┘    └┘└─┘└┘  └┘  └──┘└┘  └──┘└───┘
typ  ───┘    └┘└─┘└┘└┘└┘  └──┘└┘  └──┘└───┘
doc  ───┘    └┘└─┘└┘  └┘  └──┘└┘  └──┘└───┘
txt  ───┘    └┘   └┘  └┘  └──┘└┘  └──┘└───┘
par  ───┘    └┘   └┘  └┘  └──┘└┘  └──┘└───┘
pid  ───┘    └┘   └┘  └┘  └─────┘  └────────┘
st   ────────────────────┘└───┘└──┘└───┘└───┘└─
1299    intros s1 s2 h,
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid          └──────┘
st   ───────────────┘└─
1300    apply lift_rel_rec (λ c1 c2, ∃ s S SS,
id           └──────────┘                  
src    └────┘└──────────┘  └──────┘└─────┘
typ    └────┘└──────────┘  └──────┘└─────┘
doc    └────┘              └──────┘ └─────┘ 
txt    └────┘              └──────┘ └─────┘ 
par    └────┘              └──────┘ └─────┘ 
pid                       └──────┘ └─────┘ 
st   ─────────────────────────────────────────
1301        c1 = destruct (append s (join (append S (join SS)))) ∧
src  ─────┘                                       └───┘ 
typ  ─────┘                                       └───┘ 
doc  ─────┘                                       └───┘ 
txt  ─────┘                                       └───┘ 
par  ─────┘                                       └───┘ 
pid  ─────┘                                       └───┘ 
st   ─────────────────────────────────────────────────────────────
1302        c2 = destruct (append s (append (join S) (join (map join SS)))))
id                                  └────┘                 └─┘ └──┘
src  ─────┘                    └────┘      └┘      └─┘└──┘  └─────
typ  ─────┘                    └────┘      └┘      └─┘└──┘  └─────
doc  ─────┘                    └────┘      └┘      └─┘└──┘  └─────
txt  ─────┘                                └┘               └─────
par  ─────┘                                └┘               └─────
pid  ─────┘                                └┘               └─────
st   ───────────────────────────────────────────────────────────────────────
1303      _ (destruct s1) (destruct s2)
id                   └┘   └──────┘ └┘
src  ─────┘           └┘ └──────┘  └─
typ  ─────┘         └┘└┘ └──────┘└┘└─
doc  ─────┘           └┘ └──────┘  └─
txt  ─────┘           └┘           └─
par  ─────┘           └┘           └─
pid  ─────┘           └┘           └─
st   ──────────────────────────────────
1304      (let ⟨s, S, SS, h1, h2⟩ := h in ⟨s, S, SS, by simp [h1], by simp [h2]⟩),
id                 └┘                                     └┘            └┘
src  ───┘      └┘ └┘  └┘  └┘  └───┘ └──┘  └┘ └┘  └┘  └────┘  └┘  └────┘  └┘
typ  ───┘     └┘└┘└┘└┘  └┘  └───┘└──┘  └┘ └┘  └┘  └────┘└┘└┘  └────┘└┘└┘
doc  ───┘      └┘ └┘  └┘  └┘  └───┘ └──┘  └┘ └┘  └┘  └────┘  └┘  └────┘  └┘
txt  ───┘      └┘ └┘  └┘  └┘  └───┘ └──┘  └┘ └┘  └┘  └────┘  └┘  └────┘  └┘
par  ───┘      └┘ └┘  └┘  └┘  └───┘ └──┘  └┘ └┘  └┘  └────┘  └┘  └────┘  └┘
pid  ───┘      └┘ └┘  └┘  └┘  └───┘ └──┘  └┘ └┘  └┘  └─────┘  └─┘  └─────┘  └─┘
st   ────────────────────────────────────────────────┘└────────┘└──┘└────────┘└┘└─
1305    intros c1 c2 h,
src    └────────────┘
typ    └────────────┘
doc    └────────────┘
txt    └────────────┘
par    └────────────┘
pid          └──────┘
st   ───────────────┘└─
1306    exact match c1, c2, h with ._, ._, ⟨s, S, SS, rfl, rfl⟩ := begin
id                 └┘  └┘                                └─┘
src    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘  └┘   └┘└─┘└───┘     
typ    └────┘     └┘└┘└┘└┘└────┘  └┘  └┘  └┘ └┘  └┘   └┘└─┘└───┘     
doc    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘  └┘   └┘   └───┘     
txt    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘  └┘   └┘   └───┘     
par    └────┘       └┘  └┘ └────┘  └┘  └┘  └┘ └┘  └┘   └┘   └───┘     
pid                └┘  └┘ └────┘  └┘  └┘  └┘ └┘  └┘   └┘   └───┘     
st   ────────────────────────────────────────────────────────────┘└─────
1307      clear _match h h,
src  ───┘└──────────────┘└─
typ  ───┘└──────────────┘└─
doc  ───┘└──────────────┘└─
txt  ───┘└──────────────┘└─
par  ───┘└──────────────┘└─
pid  ──────────────────────
st   ───────────────────┘└─
1308      apply wseq.cases_on s _ (λ a s, _) (λ s, _); simp; simp,
id             └───────────┘ 
src  ───┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ─────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ───┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ───┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ─────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ─────────┘              └─┘  └───────┘  └───────────────────
st   ──────────────────────────────────────────────────────────┘└─
1309      { apply wseq.cases_on S _ (λ s S, _) (λ S, _); simp; simp,
id               └───────────┘ 
src  ─────┘└────┘└───────────┘ └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
typ  ───────────┘└───────────┘└─┘  └───────┘  └──────┘└──┘└┘└──┘└─
doc  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
txt  ─────┘└────┘              └─┘  └───────┘  └────┘└┘└──┘└┘└──┘└─
par  ───────────┘              └─┘  └───────┘  └──────┘└──┘└┘└──┘└─
pid  ───────────┘              └─┘  └───────┘  └───────────────────
st   ────┘└──────────────────────────────────────────────────────┘└─
1310        { apply wseq.cases_on SS _ (λ S SS, _) (λ SS, _); simp; simp,
id                 └───────────┘ └┘
src  ───────┘└────┘└───────────┘  └─┘  └────────┘  └─────┘└┘└──┘└┘└──┘└─
typ  ─────────────┘└───────────┘└┘└─┘  └────────┘  └───────┘└──┘└┘└──┘└─
doc  ───────┘└────┘               └─┘  └────────┘  └─────┘└┘└──┘└┘└──┘└─
txt  ───────┘└────┘               └─┘  └────────┘  └─────┘└┘└──┘└┘└──┘└─
par  ─────────────┘               └─┘  └────────┘  └───────┘└──┘└┘└──┘└─
pid  ─────────────┘               └─┘  └────────┘  └────────────────────
st   ──────┘└─────────────────────────────────────────────────────────┘└─
1311          { refine ⟨nil, S, SS, _, _⟩; simp },
id                     └─┘    └┘
src  ─────────┘└─────┘ └─┘└┘ └┘  └─────┘└┘└───┘└──
typ  ────────────────┘ └─┘└┘└┘└┘└───────┘└───┘└──
doc  ─────────┘└─────┘ └─┘└┘ └┘  └─────┘└┘└───┘└──
txt  ─────────┘└─────┘    └┘ └┘  └─────┘└┘└───┘└──
par  ────────────────┘    └┘ └┘  └───────┘└───┘└──
pid  ────────────────┘    └┘ └┘  └────────────────
st   ────────┘└───────────────────────────────┘└─
1312          { refine ⟨nil, nil, SS, _, _⟩; simp } },
id                          └─┘  └┘
src  ─────────┘└─────┘    └┘└─┘└┘  └─────┘└┘└───┘└────
typ  ────────────────┘    └┘└─┘└┘└┘└───────┘└───┘└────
doc  ─────────┘└─────┘    └┘└─┘└┘  └─────┘└┘└───┘└────
txt  ─────────┘└─────┘    └┘   └┘  └─────┘└┘└───┘└────
par  ────────────────┘    └┘   └┘  └───────┘└───┘└────
pid  ────────────────┘    └┘   └┘  └──────────────────
st   ───────────────────────────────────────────┘└─┘└─
1313        { exact ⟨s, S, SS, rfl, rfl⟩ },
id                      └┘       └─┘
src  ─────────────┘  └┘ └┘  └┘   └┘└─┘└────
typ  ─────────────┘ └┘└┘└┘└┘   └┘└─┘└────
doc  ─────────────┘  └┘ └┘  └┘   └┘   └────
txt  ─────────────┘  └┘ └┘  └┘   └┘   └────
par  ─────────────┘  └┘ └┘  └┘   └┘   └────
pid  ─────────────┘  └┘ └┘  └┘   └┘   └────
st   ──────┘└──────────────────────────┘└─
1314        { refine ⟨nil, S, SS, _, _⟩; simp } },
id                   └─┘    └┘
src  ───────┘└─────┘ └─┘└┘ └┘  └─────┘└┘└───┘└────
typ  ──────────────┘ └─┘└┘└┘└┘└───────┘└───┘└────
doc  ───────┘└─────┘ └─┘└┘ └┘  └─────┘└┘└───┘└────
txt  ───────┘└─────┘    └┘ └┘  └─────┘└┘└───┘└────
par  ──────────────┘    └┘ └┘  └───────┘└───┘└────
pid  ──────────────┘    └┘ └┘  └──────────────────
st   ───────────────────────────────────────┘└─┘└─
1315      { exact ⟨s, S, SS, rfl, rfl⟩ },
id                    └┘       └─┘
src  ───────────┘  └┘ └┘  └┘   └┘└─┘└────
typ  ───────────┘ └┘└┘└┘└┘   └┘└─┘└────
doc  ───────────┘  └┘ └┘  └┘   └┘   └────
txt  ───────────┘  └┘ └┘  └┘   └┘   └────
par  ───────────┘  └┘ └┘  └┘   └┘   └────
pid  ───────────┘  └┘ └┘  └┘   └┘   └────
st   ────┘└──────────────────────────┘└─
1316      { exact ⟨s, S, SS, rfl, rfl⟩ }
id                    └┘       └─┘
src  ───────────┘  └┘ └┘  └┘   └┘└─┘└───
typ  ───────────┘ └┘└┘└┘└┘   └┘└─┘└───
doc  ───────────┘  └┘ └┘  └┘   └┘   └───
txt  ───────────┘  └┘ └┘  └┘   └┘   └───
par  ───────────┘  └┘ └┘  └┘   └┘   └───
pid  ───────────┘  └┘ └┘  └┘   └┘   └───
st   ────────────────────────────────┘└─
1317    end end
src  ─────────┘
typ  ─────────┘
doc  ─────────┘
txt  ─────────┘
par  ─────────┘
pid  ────────┘
st   ────┘└───┘
1318  end
st   └─┘
1319  
1320  @[simp] theorem bind_assoc (s : wseq α) (f : α → wseq β) (g : β → wseq γ) :
id                                   └──┘           └──┘           └──┘ 
src                                  └──┘             └──┘             └──┘
typ                                  └──┘           └──┘           └──┘ 
doc    └──┘                          └──┘             └──┘             └──┘
1321    bind (bind s f) g ~ bind s (λ (x : α), bind (f x) g) :=
id     └──┘  └──┘      └──┘             └──┘     
src    └──┘  └──┘         └──┘               └──┘
typ    └──┘  └──┘      └──┘             └──┘     
doc    └──┘  └──┘         └──┘               └──┘
1322  begin
st   └─────
1323    simp [bind], rw [← map_comp f (map g), map_comp (map g ∘ f) join],
id           └──┘         └──────┘   └─┘    └──────┘  └─┘     └──┘
src    └────┘└──┘  └────┘└──────┘  └─┘ └─┘└──────┘ └─┘  └┘└──┘
typ    └────┘└──┘  └────┘└──────┘ └─┘└─┘└──────┘ └─┘└┘└──┘
doc    └────┘└──┘  └────┘          └─┘ └─┘         └─┘   └┘└──┘
txt    └────┘      └────┘              └─┘               └┘    
par    └────┘      └────┘              └─┘               └┘    
pid                └──┘              └─┘               └┘    
st   ────────────┘└────────────────────────┘└─────────────────────────┘└──
1324    apply join_join
id           └───────┘
src    └────┘└───────┘
typ    └────┘└───────┘
doc    └────┘         
txt    └────┘         
par    └────┘         
pid                  
st   ─────────────────┘
1325  end
st   └─┘
1326  
1327  instance : monad wseq :=
id              └───┘ └──┘
src             └───┘ └──┘
typ             └───┘ └──┘
doc                   └──┘
1328  { map  := @map,
id              └─┘
src             └─┘
typ             └─┘
doc             └─┘
1329    pure := @ret,
id              └─┘
src             └─┘
typ             └─┘
doc             └─┘
1330    bind := @bind }
id              └──┘
src             └──┘
typ             └──┘
doc             └──┘
1331  
1332  /-
1333    Unfortunately, wseq is not a lawful monad, because it does not satisfy
1334    the monad laws exactly, only up to sequence equivalence.
1335    Furthermore, even quotienting by the equivalence is not sufficient,
1336    because the join operation involves lists of quotient elements,
1337    with a lifted equivalence relation, and pure quotients cannot handle
1338    this type of construction.
1339  
1340  instance : is_lawful_monad wseq :=
1341  { id_map := @map_id,
1342    bind_pure_comp_eq_map := @bind_ret,
1343    pure_bind := @ret_bind,
1344    bind_assoc := @bind_assoc }
1345  -/
1346  
1347  end wseq